From fd2daa57d609dbbf25be3ff3ffde295a3e9d175c Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 9 Jun 2026 09:50:47 +0530 Subject: [PATCH 001/108] Update event_manager.c --- uploadstblogs/src/event_manager.c | 118 +----------------------------- 1 file changed, 1 insertion(+), 117 deletions(-) diff --git a/uploadstblogs/src/event_manager.c b/uploadstblogs/src/event_manager.c index ff9c3cb9..1670e40a 100755 --- a/uploadstblogs/src/event_manager.c +++ b/uploadstblogs/src/event_manager.c @@ -36,9 +36,7 @@ #if defined(IARM_ENABLED) #include "libIBus.h" #include "sysMgr.h" -#ifdef EN_MAINTENANCE_MANAGER -#include "maintenanceMGR.h" -#endif + static bool iarm_initialized = false; #define IARM_UPLOADSTB_EVENT "UploadSTBLogsEvent" @@ -53,19 +51,6 @@ static bool iarm_initialized = false; #define LOG_UPLOAD_FAILED 1 #define LOG_UPLOAD_ABORTED 2 -#define MAINT_LOGUPLOAD_COMPLETE 4 -#define MAINT_LOGUPLOAD_ERROR 5 -#define MAINT_LOGUPLOAD_INPROGRESS 16 - -// Check maintenance mode (matches script ENABLE_MAINTENANCE check) -static bool is_maintenance_enabled(void) -{ - char buffer[32] = {0}; - if (getDevicePropertyData("ENABLE_MAINTENANCE", buffer, sizeof(buffer)) == UTILS_SUCCESS) { - return (strcasecmp(buffer, "true") == 0); - } - return false; -} // Check device type (matches script DEVICE_TYPE check) static bool is_device_broadband(const RuntimeContext* ctx) @@ -81,9 +66,6 @@ void emit_privacy_abort(void) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Upload aborted due to privacy mode\n", __FUNCTION__, __LINE__); - // Send maintenance complete event (matches script behavior) - // Script sends MAINT_LOGUPLOAD_COMPLETE=4 for privacy mode, not ERROR - send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); } void emit_no_logs_reboot(const RuntimeContext* ctx) @@ -98,23 +80,12 @@ void emit_no_logs_reboot(const RuntimeContext* ctx) return; } - // Send maintenance complete event only if device is not broadband and maintenance enabled - // Matches script uploadLogOnReboot line 810: if [ "$DEVICE_TYPE" != "broadband" ] && [ "x$ENABLE_MAINTENANCE" == "xtrue" ] - if (!is_device_broadband(ctx) && is_maintenance_enabled() && ctx->rrd_flag == 0) { - send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); - } } void emit_no_logs_ondemand(void) { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Log directory empty, skipping log upload\n", __FUNCTION__, __LINE__); - - // Send maintenance complete event only if maintenance enabled (no device type check) - // Matches script uploadLogOnDemand line 746: if [ "x$ENABLE_MAINTENANCE" == "xtrue" ] - if (is_maintenance_enabled()) { - send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); - } } void emit_upload_success(const RuntimeContext* ctx, const SessionState* session) @@ -143,11 +114,6 @@ void emit_upload_success(const RuntimeContext* ctx, const SessionState* session) // Send success events (matches script behavior) send_iarm_event("LogUploadEvent", LOG_UPLOAD_SUCCESS); - - // Send maintenance event only if device is not broadband and maintenance enabled - if (ctx && !is_device_broadband(ctx) && is_maintenance_enabled() && ctx->rrd_flag == 0) { - send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); - } } void emit_upload_failure(const RuntimeContext* ctx, const SessionState* session) @@ -175,10 +141,6 @@ void emit_upload_failure(const RuntimeContext* ctx, const SessionState* session) // Send failure events (matches script behavior) send_iarm_event("LogUploadEvent", LOG_UPLOAD_FAILED); - // Send maintenance event only if device is not broadband and maintenance enabled - if (!is_device_broadband(ctx) && is_maintenance_enabled()) { - send_iarm_event_maintenance(MAINT_LOGUPLOAD_ERROR); - } } void emit_upload_aborted(void) @@ -187,30 +149,6 @@ void emit_upload_aborted(void) "[%s:%d] Not Uploading Logs with DCM \n", __FUNCTION__, __LINE__); send_iarm_event("LogUploadEvent", LOG_UPLOAD_FAILED); - send_iarm_event_maintenance(MAINT_LOGUPLOAD_ERROR); -} - -void emit_fallback(UploadPath from_path, UploadPath to_path) -{ - const char* from_str = (from_path == PATH_DIRECT) ? "Direct" : "CodeBig"; - const char* to_str = (to_path == PATH_DIRECT) ? "Direct" : "CodeBig"; - - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Upload fallback: switching from %s to %s path\n", - __FUNCTION__, __LINE__, from_str, to_str); - - // Note: Script doesn't send specific fallback events, just logs the switch -} - -void emit_upload_start(void) -{ - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Starting upload operation\n", __FUNCTION__, __LINE__); - - // Note: MAINT_LOGUPLOAD_INPROGRESS is sent in different contexts: - // 1. When lock acquisition fails (handled in main()) - // 2. During normal upload start (here) - but script doesn't send this here - // Script only sends MAINT_LOGUPLOAD_INPROGRESS on lock failure, not normal start } #ifndef GTEST_ENABLE @@ -344,50 +282,6 @@ void send_iarm_event(const char* event_name, int event_code) } } -/** - * @brief Send maintenance manager IARM event - * Based on rdkfwupdater iarmInterface.c eventManager() MaintenanceMGR section - */ -void send_iarm_event_maintenance(int maint_event_code) -{ -#ifdef EN_MAINTENANCE_MANAGER - if (!init_iarm_connection()) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] IARM not initialized, skipping maintenance event\n", __FUNCTION__, __LINE__); - return; - } - - IARM_Bus_MaintMGR_EventData_t infoStatus; - IARM_Result_t ret_code; - - memset(&infoStatus, 0, sizeof(IARM_Bus_MaintMGR_EventData_t)); - - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Sending MaintenanceMGR event with code: %d\n", - __FUNCTION__, __LINE__, maint_event_code); - - infoStatus.data.maintenance_module_status.status = (IARM_Maint_module_status_t)maint_event_code; - - ret_code = IARM_Bus_BroadcastEvent(IARM_BUS_MAINTENANCE_MGR_NAME, - (IARM_EventId_t)IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, - (void*)&infoStatus, sizeof(infoStatus)); - - if (ret_code == IARM_RESULT_SUCCESS) { - RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, - "[%s:%d] MaintenanceMGR event sent successfully: %d\n", - __FUNCTION__, __LINE__, maint_event_code); - } else { - RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, - "[%s:%d] MaintenanceMGR event failed: %d (result: %d)\n", - __FUNCTION__, __LINE__, maint_event_code, ret_code); - } -#else - RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, - "[%s:%d] Maintenance Manager not enabled, skipping event: %d\n", - __FUNCTION__, __LINE__, maint_event_code); -#endif -} - /** * @brief Cleanup IARM connection * Based on rdkfwupdater iarmrInterface.c term_event_handler() @@ -412,13 +306,6 @@ void send_iarm_event(const char* event_name, int event_code) __FUNCTION__, __LINE__, event_name ? event_name : "NULL", event_code); } -void send_iarm_event_maintenance(int maint_event_code) -{ - RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, - "[%s:%d] IARM disabled - would send maintenance event: %d\n", - __FUNCTION__, __LINE__, maint_event_code); -} - void cleanup_iarm_connection(void) { // No-op when IARM disabled @@ -430,8 +317,5 @@ void emit_folder_missing_error(void) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Required folder missing for log upload\n", __FUNCTION__, __LINE__); - - // Send maintenance complete event (matches script behavior) - send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); } From 0e603927da5e4f4ad8baf549bd986ea784523f1a Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 9 Jun 2026 09:51:51 +0530 Subject: [PATCH 002/108] Update event_manager.h --- uploadstblogs/include/event_manager.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/uploadstblogs/include/event_manager.h b/uploadstblogs/include/event_manager.h index 716b3c8b..ee342503 100755 --- a/uploadstblogs/include/event_manager.h +++ b/uploadstblogs/include/event_manager.h @@ -67,11 +67,6 @@ void emit_upload_failure(const RuntimeContext* ctx, const SessionState* session) */ void emit_upload_aborted(void); -/** - * @brief Emit upload start event - */ -void emit_upload_start(void); - /** * @brief Emit fallback event * @param from_path Original path @@ -86,11 +81,6 @@ void emit_fallback(UploadPath from_path, UploadPath to_path); */ void send_iarm_event(const char* event_name, int event_code); -/** - * @brief Send maintenance manager IARM event - * @param maint_event_code Maintenance event code - */ -void send_iarm_event_maintenance(int maint_event_code); /** * @brief Cleanup IARM connection resources From 0ea4dedfabbab38656bcea2c85c77312cb8841ca Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:13:17 +0530 Subject: [PATCH 003/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index 7f29b2eb..144a8b8d 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -243,9 +243,6 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); - if (is_maintenance_enabled()) { - send_iarm_event_maintenance(16); - } return 1; } @@ -358,10 +355,6 @@ int uploadstblogs_execute(int argc, char** argv) /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); - /* Script sends MAINT_LOGUPLOAD_INPROGRESS when another instance is already running */ - if (is_maintenance_enabled()) { - send_iarm_event_maintenance(16); // Matches script: eventSender "MaintenanceMGR" $MAINT_LOGUPLOAD_INPROGRESS - } return 1; } @@ -428,11 +421,6 @@ int uploadstblogs_execute(int argc, char** argv) return 0; } - /* Note: STRAT_NO_LOGS removed - each strategy now checks for logs internally */ - - /* Emit upload start event (matches script MAINT_LOGUPLOAD_INPROGRESS) */ - emit_upload_start(); - /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { // RRD: Upload pre-existing archive file directly (provided via command line) From 34384750a633118e3d220fd889fa7d1e46592f0b Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:17:08 +0530 Subject: [PATCH 004/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index 144a8b8d..c513a8e9 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -297,9 +297,6 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) return 0; } - /* Emit upload start event */ - emit_upload_start(); - /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { if (!file_exists(ctx.rrd_file)) { From 614105c2a20fae73c31fba72f2ae8d6725fed878 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:34:20 +0530 Subject: [PATCH 005/108] Update event_manager.c --- uploadstblogs/src/event_manager.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/uploadstblogs/src/event_manager.c b/uploadstblogs/src/event_manager.c index 1670e40a..00f50980 100755 --- a/uploadstblogs/src/event_manager.c +++ b/uploadstblogs/src/event_manager.c @@ -52,15 +52,6 @@ static bool iarm_initialized = false; #define LOG_UPLOAD_ABORTED 2 -// Check device type (matches script DEVICE_TYPE check) -static bool is_device_broadband(const RuntimeContext* ctx) -{ - if (!ctx) { - return false; - } - return (strcmp(ctx->device_type, "broadband") == 0); -} - void emit_privacy_abort(void) { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, From 7669569d3d6e41ef9fed4d2aeb5602924cb260c2 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 9 Jun 2026 19:08:19 +0530 Subject: [PATCH 006/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index c513a8e9..89828dc7 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -243,6 +243,9 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); + if (is_maintenance_enabled()) { + send_iarm_event_maintenance(16); + } return 1; } @@ -297,6 +300,9 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) return 0; } + /* Emit upload start event */ + emit_upload_start(); + /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { if (!file_exists(ctx.rrd_file)) { @@ -352,6 +358,10 @@ int uploadstblogs_execute(int argc, char** argv) /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); + /* Script sends MAINT_LOGUPLOAD_INPROGRESS when another instance is already running */ + if (is_maintenance_enabled()) { + send_iarm_event_maintenance(16); // Matches script: eventSender "MaintenanceMGR" $MAINT_LOGUPLOAD_INPROGRESS + } return 1; } @@ -418,6 +428,11 @@ int uploadstblogs_execute(int argc, char** argv) return 0; } + /* Note: STRAT_NO_LOGS removed - each strategy now checks for logs internally */ + + /* Emit upload start event (matches script MAINT_LOGUPLOAD_INPROGRESS) */ + emit_upload_start(); + /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { // RRD: Upload pre-existing archive file directly (provided via command line) @@ -478,4 +493,3 @@ int main(int argc, char** argv) } #endif /* UPLOADSTBLOGS_BUILD_BINARY */ - From f308f14053446235b380486f2a2039dbc9601765 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 10 Jun 2026 09:32:39 +0530 Subject: [PATCH 007/108] Update backup_logs.h --- backup_logs/include/backup_logs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backup_logs/include/backup_logs.h b/backup_logs/include/backup_logs.h index da5ba328..29325d5a 100644 --- a/backup_logs/include/backup_logs.h +++ b/backup_logs/include/backup_logs.h @@ -26,6 +26,13 @@ extern "C" { #endif +/** Sentinel written by backup_logs after successful completion. + * Cross-repo interface: also referenced by reboot-manager's update-prev-reboot-info + * and telemetry's telemetry2_0. + * Any path change MUST be coordinated with the reboot-manager and telemetry repositories. */ + +#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" + /** * @brief Main entry point for backup_logs system * From 33986636bb1e584f04e6fdecfdc0a8f852e3fe0e Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 10 Jun 2026 09:40:15 +0530 Subject: [PATCH 008/108] Update backup_logs.c --- backup_logs/src/backup_logs.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/backup_logs/src/backup_logs.c b/backup_logs/src/backup_logs.c index dc608e77..2c607162 100644 --- a/backup_logs/src/backup_logs.c +++ b/backup_logs/src/backup_logs.c @@ -33,6 +33,8 @@ #include "special_files.h" #include "system_utils.h" #include +#include +#include #define BACKUP_LOGS_VERSION "1.0.0" #define BACKUP_LOGS_BUILD_DATE __DATE__ @@ -302,6 +304,21 @@ int backup_logs_main(int argc, char *argv[]) { } RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Backup process completed successfully\n"); + /* Write completion sentinel for downstream consumers (reboot-manager, telemetry). + * /tmp/ is volatile — no stale-sentinel risk across reboots. + * Non-fatal: if open() fails, downstream services will time out and annotate gracefully. */ + { + int sentinel_fd = open(BACKUP_LOGS_DONE_FLAG, O_CREAT | O_WRONLY, 0644); + if (sentinel_fd < 0) + { + RDK_LOG(RDK_LOG_WARN, LOG_BACKUP_LOGS, "Failed to create sentinel %s: %s\n", BACKUP_LOGS_DONE_FLAG, strerror(errno)); + } + else + { + close(sentinel_fd); + RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Sentinel written: %s\n", BACKUP_LOGS_DONE_FLAG); + } + } return EXIT_SUCCESS; } #ifndef GTEST_ENABLE From 2bb753054935a6b2ce989dc7285aaf13388c883b Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 10 Jun 2026 09:43:51 +0530 Subject: [PATCH 009/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index 89828dc7..03890475 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -243,9 +243,6 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); - if (is_maintenance_enabled()) { - send_iarm_event_maintenance(16); - } return 1; } @@ -300,9 +297,6 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) return 0; } - /* Emit upload start event */ - emit_upload_start(); - /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { if (!file_exists(ctx.rrd_file)) { @@ -358,10 +352,6 @@ int uploadstblogs_execute(int argc, char** argv) /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); - /* Script sends MAINT_LOGUPLOAD_INPROGRESS when another instance is already running */ - if (is_maintenance_enabled()) { - send_iarm_event_maintenance(16); // Matches script: eventSender "MaintenanceMGR" $MAINT_LOGUPLOAD_INPROGRESS - } return 1; } @@ -428,11 +418,6 @@ int uploadstblogs_execute(int argc, char** argv) return 0; } - /* Note: STRAT_NO_LOGS removed - each strategy now checks for logs internally */ - - /* Emit upload start event (matches script MAINT_LOGUPLOAD_INPROGRESS) */ - emit_upload_start(); - /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { // RRD: Upload pre-existing archive file directly (provided via command line) From f5f8333eb58646fb204ce84f895eec32615af4ff Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Fri, 12 Jun 2026 12:28:22 +0530 Subject: [PATCH 010/108] Update context_manager.c --- uploadstblogs/src/context_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uploadstblogs/src/context_manager.c b/uploadstblogs/src/context_manager.c index a713ed2e..44d1cdfe 100755 --- a/uploadstblogs/src/context_manager.c +++ b/uploadstblogs/src/context_manager.c @@ -159,7 +159,7 @@ bool init_context(RuntimeContext* ctx) rdk_logger_ext_config_t config = { .pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */ .loglevel = RDK_LOG_INFO, /* Default log level */ - .output = RDKLOG_OUTPUT_CONSOLE, /* Output to console (stdout/stderr) */ + .output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ .format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */ .pFilePolicy = NULL /* Not using file output, so NULL */ }; From b8cf6407c374edde3cc32f65d69a427d69bb3f7e Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:06:14 +0530 Subject: [PATCH 011/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 52 +++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 21b4a196..e321e3df 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -45,6 +45,58 @@ #define STATUS_FILE "/opt/loguploadstatus.txt" #define DCM_TEMP_DIR "/tmp/DCM" + +/* ========================== + Boot Synchronisation Sentinels (REQ-SYNC-001, REQ-SYNC-003) + All sentinels are volatile /tmp files; cleared automatically on every reboot. + ========================== */ + +/** backup_logs completion sentinel — written by the backup_logs binary after a + * successful backup_logs_execute(). + * Hard gate: if absent at upload time, PreviousLogs/ is incomplete and the reboot + * upload is aborted (nothing safe to archive). + * Cross-repo interface: path is also defined in backup_logs/include/backup_logs.h. + * Any change MUST be coordinated with the reboot-manager and telemetry repositories. */ +#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" + +/** Poll interval and timeout for the backup_logs hard-gate sentinel. The timeout is + * intentionally shorter than REBOOT_POLL_TIMEOUT_S; if backup_logs hasn't finished + * within this window it is considered failed and the upload is aborted. */ +#define BACKUP_LOGS_POLL_INTERVAL_S 1u +#ifdef GTEST_ENABLE +#define BACKUP_LOGS_POLL_TIMEOUT_S 2u +#else +#define BACKUP_LOGS_POLL_TIMEOUT_S 60u +#endif + +/** Reboot reason completion sentinel — written by update-prev-reboot-info (reboot-manager). + * Presence guarantees /opt/secure/reboot/previousreboot.info is written and complete. + * Cross-repo interface: path is also defined in reboot-manager. + * Any change MUST be coordinated with the reboot-manager repository. */ +#define PATH_FLAG_INVOCATION "/tmp/Update_rebootInfo_invoked" + +/** Trigger file written by uploadstblogs when PATH_FLAG_INVOCATION is absent at upload + * time, signalling reboot-manager to perform an immediate reboot-reason update. + * Cross-repo interface: consumed by reboot-manager/update-prev-reboot-info. + * Any path change MUST be coordinated with reboot-manager. */ +#define TRIGGER_REBOOT_INFO_UPDATE "/tmp/.trigger_reboot_info_update" + +/** Poll interval (seconds) for the reboot-reason prerequisite sentinel. */ +#define REBOOT_POLL_INTERVAL_S 1u + +/** Total poll timeout (seconds) for the reboot-reason prerequisite sentinel. + * For unit tests (GTEST_ENABLE) a shorter value avoids multi-minute waits. */ +#ifdef GTEST_ENABLE +#define REBOOT_POLL_TIMEOUT_S 2u +#else +#define REBOOT_POLL_TIMEOUT_S 120u +#endif + +/** Annotation code set in SessionState when the reboot-reason sentinel times out. + * Upload always proceeds; this records that previousreboot.info was unavailable. */ +#define ANNOTATION_REBOOT_REASON_UNAVAILABLE 1 + + /* ========================== Enumerations ========================== */ From 47ab88cabf469cb5eadae223acba28d6b3061066 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:10:00 +0530 Subject: [PATCH 012/108] Update strategies.c --- uploadstblogs/src/strategies.c | 141 +++++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 42 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 0a4fb090..05689188 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -641,6 +641,24 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting setup phase\n", __FUNCTION__, __LINE__); + // Hard gate: wait for backup_logs to complete before touching PreviousLogs/. + // If the sentinel is absent, PreviousLogs/ may be incomplete — abort. + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Waiting for backup_logs sentinel %s (timeout %us)\n", + __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_FLAG, BACKUP_LOGS_POLL_TIMEOUT_S); + + if (wait_for_backup_logs() != 0) { + RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, + "[%s:%d] backup_logs sentinel not present after %us. " + "PreviousLogs/ may be incomplete. Aborting reboot upload.\n", + __FUNCTION__, __LINE__, BACKUP_LOGS_POLL_TIMEOUT_S); + return -1; + } + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] backup_logs sentinel detected. PreviousLogs/ is complete.\n", + __FUNCTION__, __LINE__); + // Check if PREV_LOG_PATH exists and has .txt or .log files // Script uploadLogOnReboot lines 805-816: // ret=`ls $PREV_LOG_PATH/*.txt` @@ -659,57 +677,54 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) return -1; } - // Check system uptime and sleep if needed - // Script lines 818-836: if uptime < 900s, sleep 330s - double uptime_seconds = 0.0; - if (get_system_uptime(&uptime_seconds)) { - if (uptime_seconds < 900.0) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] System uptime %.0f seconds < 900s, sleeping for 330s\n", - __FUNCTION__, __LINE__, uptime_seconds); - - // Script checks ENABLE_MAINTENANCE but both paths result in 330s sleep - // For simplicity, just sleep (background job with wait has same effect) -#ifndef L2_TEST_ENABLED - sleep(330); -#endif - - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Done sleeping\n", __FUNCTION__, __LINE__); + // Wait for reboot reason sentinel (replaces sleep(330)). + // STEP 1: Write trigger to prompt update-prev-reboot-info if sentinel is absent. + // STEP 2: Poll until sentinel appears or timeout. Upload always proceeds. + { + trigger_reboot_info_update(); + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", + __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); + + if (wait_for_reboot_reason() != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] Reboot reason sentinel not present after %us. " + "Upload proceeds with reboot-reason annotation.\n", + __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); + set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); } else { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Device uptime %.0f seconds >= 900s, skipping sleep\n", - __FUNCTION__, __LINE__, uptime_seconds); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", + __FUNCTION__, __LINE__); } - } else { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] Failed to get system uptime, skipping sleep\n", - __FUNCTION__, __LINE__); + /* Always proceed — backup_logs succeeded; upload must occur */ } - // Clean up old log backup directories (older than 3 days) - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Cleaning old log backup directories (3+ days)\n", __FUNCTION__, __LINE__); - int removed_dirs = cleanup_old_log_backups(ctx->log_path, 3); - if (removed_dirs > 0) { - RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, "[%s:%d] Removed %d old log backup directories\n", __FUNCTION__, __LINE__, removed_dirs); - } else { - RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, "[%s:%d] No old log backup directories removed\n", __FUNCTION__, __LINE__); + // Delete old backup files (3+ days old) + // Remove old timestamp directories and logbackup directories + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Cleaning old backups (3+ days)\n", __FUNCTION__, __LINE__); + + int removed = remove_old_directories(ctx->log_path, "*-*-*-*-*M-", 3); + if (removed > 0) { + RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, + "[%s:%d] Removed %d old timestamp directories\n", + __FUNCTION__, __LINE__, removed); } + removed = remove_old_directories(ctx->log_path, "*-*-*-*-*M-logbackup", 3); + if (removed > 0) { + RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, + "[%s:%d] Removed %d old logbackup directories\n", + __FUNCTION__, __LINE__, removed); + } + // Create timestamp for permanent log path char timestamp[64]; time_t now = time(NULL); - struct tm tm_utc; - size_t timestamp_len; - if (gmtime_r(&now, &tm_utc) == NULL) { - RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Failed to get UTC time\n", __FUNCTION__, __LINE__); - return -1; - } - timestamp_len = strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-logbackup", &tm_utc); - if (timestamp_len == 0U) { - RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Failed to format timestamp for permanent log path\n", __FUNCTION__, __LINE__); - return -1; - } + struct tm* tm_info = localtime(&now); + strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-logbackup", tm_info); char perm_log_path[MAX_PATH_LENGTH]; int written = snprintf(perm_log_path, sizeof(perm_log_path), "%s/%s", @@ -781,6 +796,48 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) return 0; } +/** + * @brief Archive phase for REBOOT/NON_DCM strategy + * + * Shell script equivalent (uploadLogOnReboot lines 853-869): + * - Collect PCAP files to PREV_LOG_PATH if mediaclient + * - Create tar.gz archive from PREV_LOG_PATH + * - Sleep 60 seconds + */ +static int reboot_archive(RuntimeContext* ctx, SessionState* session) +{ + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] REBOOT/NON_DCM: Starting archive phase\n", __FUNCTION__, __LINE__); + + // Collect PCAP files directly to PREV_LOG_PATH if mediaclient + if (ctx->include_pcap) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Collecting PCAP file to PREV_LOG_PATH\n", __FUNCTION__, __LINE__); + int count = collect_pcap_logs(ctx, ctx->prev_log_path); + if (count > 0) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Collected %d PCAP file\n", __FUNCTION__, __LINE__, count); + } + } + + // Create archive from PREV_LOG_PATH (files already have timestamps) + int ret = create_archive(ctx, session, ctx->prev_log_path); + if (ret != 0) { + RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, + "[%s:%d] Failed to create archive\n", __FUNCTION__, __LINE__); + return -1; + } +#ifndef L2_TEST_ENABLED + sleep(60); +#endif + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] REBOOT/NON_DCM: Archive phase complete\n", __FUNCTION__, __LINE__); + + return 0; +} + + /** * @brief Archive phase for REBOOT/NON_DCM strategy * From 8572fb0ee6445cf94519b839c4ef255ca11307fd Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:13:47 +0530 Subject: [PATCH 013/108] Update strategies.c --- uploadstblogs/src/strategies.c | 42 ---------------------------------- 1 file changed, 42 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 05689188..393ed67c 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -796,48 +796,6 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) return 0; } -/** - * @brief Archive phase for REBOOT/NON_DCM strategy - * - * Shell script equivalent (uploadLogOnReboot lines 853-869): - * - Collect PCAP files to PREV_LOG_PATH if mediaclient - * - Create tar.gz archive from PREV_LOG_PATH - * - Sleep 60 seconds - */ -static int reboot_archive(RuntimeContext* ctx, SessionState* session) -{ - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] REBOOT/NON_DCM: Starting archive phase\n", __FUNCTION__, __LINE__); - - // Collect PCAP files directly to PREV_LOG_PATH if mediaclient - if (ctx->include_pcap) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Collecting PCAP file to PREV_LOG_PATH\n", __FUNCTION__, __LINE__); - int count = collect_pcap_logs(ctx, ctx->prev_log_path); - if (count > 0) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Collected %d PCAP file\n", __FUNCTION__, __LINE__, count); - } - } - - // Create archive from PREV_LOG_PATH (files already have timestamps) - int ret = create_archive(ctx, session, ctx->prev_log_path); - if (ret != 0) { - RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, - "[%s:%d] Failed to create archive\n", __FUNCTION__, __LINE__); - return -1; - } -#ifndef L2_TEST_ENABLED - sleep(60); -#endif - - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] REBOOT/NON_DCM: Archive phase complete\n", __FUNCTION__, __LINE__); - - return 0; -} - - /** * @brief Archive phase for REBOOT/NON_DCM strategy * From dffe63c64cf256c31cd6eb33e33690848021a3d6 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:22:37 +0530 Subject: [PATCH 014/108] Update strategies.c --- uploadstblogs/src/strategies.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 393ed67c..08b3ea28 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -660,9 +660,6 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) __FUNCTION__, __LINE__); // Check if PREV_LOG_PATH exists and has .txt or .log files - // Script uploadLogOnReboot lines 805-816: - // ret=`ls $PREV_LOG_PATH/*.txt` - // if [ ! $ret ]; then ret=`ls $PREV_LOG_PATH/*.log` if (!dir_exists(ctx->prev_log_path)) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] PREV_LOG_PATH does not exist: %s\n", @@ -677,12 +674,11 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) return -1; } - // Wait for reboot reason sentinel (replaces sleep(330)). - // STEP 1: Write trigger to prompt update-prev-reboot-info if sentinel is absent. - // STEP 2: Poll until sentinel appears or timeout. Upload always proceeds. + // Wait for reboot reason sentinel. + // Poll first — update-prev-reboot-info normally runs at boot and should already + // be done by now. Only if the sentinel is still absent after the full timeout + // do we write the trigger file to nudge reboot-manager into a retry. { - trigger_reboot_info_update(); - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); @@ -690,8 +686,9 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) if (wait_for_reboot_reason() != 0) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] Reboot reason sentinel not present after %us. " - "Upload proceeds with reboot-reason annotation.\n", + "Writing trigger to request immediate update.\n", __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); + trigger_reboot_info_update(); set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); } else { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, From f0f0cd897bef79724b9970fb88cb54de5f409076 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:27:46 +0530 Subject: [PATCH 015/108] Update strategies.c --- uploadstblogs/src/strategies.c | 37 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 08b3ea28..0a484ad3 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -698,30 +698,29 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) /* Always proceed — backup_logs succeeded; upload must occur */ } - // Delete old backup files (3+ days old) - // Remove old timestamp directories and logbackup directories - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Cleaning old backups (3+ days)\n", __FUNCTION__, __LINE__); - - int removed = remove_old_directories(ctx->log_path, "*-*-*-*-*M-", 3); - if (removed > 0) { - RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, - "[%s:%d] Removed %d old timestamp directories\n", - __FUNCTION__, __LINE__, removed); + // Clean up old log backup directories (older than 3 days) + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Cleaning old log backup directories (3+ days)\n", __FUNCTION__, __LINE__); + int removed_dirs = cleanup_old_log_backups(ctx->log_path, 3); + if (removed_dirs > 0) { + RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, "[%s:%d] Removed %d old log backup directories\n", __FUNCTION__, __LINE__, removed_dirs); + } else { + RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, "[%s:%d] No old log backup directories removed\n", __FUNCTION__, __LINE__); } - removed = remove_old_directories(ctx->log_path, "*-*-*-*-*M-logbackup", 3); - if (removed > 0) { - RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, - "[%s:%d] Removed %d old logbackup directories\n", - __FUNCTION__, __LINE__, removed); - } - // Create timestamp for permanent log path char timestamp[64]; time_t now = time(NULL); - struct tm* tm_info = localtime(&now); - strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-logbackup", tm_info); + struct tm tm_utc; + size_t timestamp_len; + if (gmtime_r(&now, &tm_utc) == NULL) { + RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Failed to get UTC time\n", __FUNCTION__, __LINE__); + return -1; + } + timestamp_len = strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-logbackup", &tm_utc); + if (timestamp_len == 0U) { + RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Failed to format timestamp for permanent log path\n", __FUNCTION__, __LINE__); + return -1; + } char perm_log_path[MAX_PATH_LENGTH]; int written = snprintf(perm_log_path, sizeof(perm_log_path), "%s/%s", From 54e3f380aa64350c0b18b58fc0fc842dd2c74e30 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:29:38 +0530 Subject: [PATCH 016/108] Update strategies.c --- uploadstblogs/src/strategies.c | 104 +++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 0a484ad3..678d164d 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -61,6 +61,110 @@ static int dcm_archive(RuntimeContext* ctx, SessionState* session); static int dcm_upload(RuntimeContext* ctx, SessionState* session); static int dcm_cleanup(RuntimeContext* ctx, SessionState* session, bool upload_success); + + +/* ---- Prerequisite sentinel helpers ---- */ + +/** + * wait_for_backup_logs - Hard gate: poll for the backup_logs completion sentinel. + * + * Polls BACKUP_LOGS_DONE_FLAG (/tmp/.backup_logs_done) every + * BACKUP_LOGS_POLL_INTERVAL_S seconds for up to BACKUP_LOGS_POLL_TIMEOUT_S seconds. + * + * Returns 0 when the sentinel is present (PreviousLogs/ is complete and safe to read). + * Returns -1 on timeout. The caller MUST abort the reboot upload on -1 — there is + * nothing safe to archive if backup_logs did not complete successfully. + */ +static int wait_for_backup_logs(void) +{ + struct timespec start, now; + struct stat st; + + clock_gettime(CLOCK_MONOTONIC, &start); + + for (;;) { + if (stat(BACKUP_LOGS_DONE_FLAG, &st) == 0) { + return 0; /* backup_logs complete — PreviousLogs/ is safe to read */ + } + + clock_gettime(CLOCK_MONOTONIC, &now); + if ((now.tv_sec - start.tv_sec) >= (time_t)BACKUP_LOGS_POLL_TIMEOUT_S) { + return -1; /* timeout — backup_logs may have failed */ + } + sleep(BACKUP_LOGS_POLL_INTERVAL_S); + } +} + +/** + * trigger_reboot_info_update - Write trigger sentinel when reboot-reason is absent. + * + * Called ONCE at the start of reboot_setup() before the polling loop. + * Writing the trigger file signals update-prev-reboot-info (reboot-manager) to + * perform an immediate reboot-reason update within the upload window. + * + * Cross-repo interface: TRIGGER_REBOOT_INFO_UPDATE consumed by reboot-manager. + */ +static void trigger_reboot_info_update(void) +{ + struct stat st; + + if (stat(PATH_FLAG_INVOCATION, &st) != 0) { + int fd = open(TRIGGER_REBOOT_INFO_UPDATE, O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd >= 0) { + close(fd); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Wrote reboot reason trigger: %s\n", + __FUNCTION__, __LINE__, TRIGGER_REBOOT_INFO_UPDATE); + } + } +} + +/** + * wait_for_reboot_reason - Poll for the reboot-reason completion sentinel. + * + * Polls PATH_FLAG_INVOCATION (/tmp/Update_rebootInfo_invoked) every + * REBOOT_POLL_INTERVAL_S seconds for up to REBOOT_POLL_TIMEOUT_S seconds. + * + * Uses clock_gettime(CLOCK_MONOTONIC) to measure elapsed time accurately, + * avoiding cumulative drift from EINTR-interrupted sleep() calls. + * + * Returns 0 when the sentinel is present (previousreboot.info is ready). + * Returns -1 on timeout. A timeout does NOT abort the upload; the caller + * annotates the session and proceeds. + */ +static int wait_for_reboot_reason(void) +{ + struct timespec start, now; + struct stat st; + + clock_gettime(CLOCK_MONOTONIC, &start); + + for (;;) { + if (stat(PATH_FLAG_INVOCATION, &st) == 0) { + return 0; /* reboot reason ready */ + } + + clock_gettime(CLOCK_MONOTONIC, &now); + if ((now.tv_sec - start.tv_sec) >= (time_t)REBOOT_POLL_TIMEOUT_S) { + return -1; /* timeout */ + } + sleep(REBOOT_POLL_INTERVAL_S); + } +} + +/** + * set_upload_annotation - Record a prerequisite-failure annotation in the session. + * + * @param session Active session. + * @param annotation One of ANNOTATION_* codes defined in uploadstblogs_types.h. + */ +static void set_upload_annotation(SessionState *session, int annotation) +{ + if (session) { + session->upload_annotations |= (1 << annotation); + } +} + /** * @brief Read upload_flag from DCMSettings.conf * @return true if upload is enabled, false otherwise From 736bfb8da90345409a69ac310165b85700a18142 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:30:23 +0530 Subject: [PATCH 017/108] Update strategies.c --- uploadstblogs/src/strategies.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 678d164d..0a1453b6 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "strategy_handler.h" #include "archive_manager.h" #include "upload_engine.h" From c32d290d04aa15f4ef92c679875413ca4e341b74 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 13:29:58 +0530 Subject: [PATCH 018/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index e321e3df..c02048de 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -342,6 +342,7 @@ typedef struct { bool used_fallback; /**< Whether fallback was used */ bool success; /**< Overall success status */ char archive_file[MAX_FILENAME_LENGTH]; /**< Generated archive filename */ + int upload_annotations; /**< Bitmask of ANNOTATION_* codes set during prerequisite fallback */ } SessionState; /* ========================== From 256a2412963392d42361023165fc1cd4d640f0e4 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:41:03 +0530 Subject: [PATCH 019/108] Update strategies.c --- uploadstblogs/src/strategies.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 0a1453b6..35c0d80c 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -321,10 +321,6 @@ static int dcm_archive(RuntimeContext* ctx, SessionState* session) "[%s:%d] Failed to create archive\n", __FUNCTION__, __LINE__); return -1; } - -#ifndef L2_TEST_ENABLED - sleep(60); -#endif RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] DCM: Archive phase complete\n", __FUNCTION__, __LINE__); From a2fb27791ebc2a5bcbe96b5a2681c916c3dbcc8d Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:42:46 +0530 Subject: [PATCH 020/108] Update strategies.c --- uploadstblogs/src/strategies.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 35c0d80c..2996ed81 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -925,9 +925,6 @@ static int reboot_archive(RuntimeContext* ctx, SessionState* session) "[%s:%d] Failed to create archive\n", __FUNCTION__, __LINE__); return -1; } -#ifndef L2_TEST_ENABLED - sleep(60); -#endif RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Archive phase complete\n", __FUNCTION__, __LINE__); From 6b82e55c6b798f3eb746e9c3d15e2b2c6973b231 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:45:44 +0530 Subject: [PATCH 021/108] Update strategies.c --- uploadstblogs/src/strategies.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 2996ed81..40bc395a 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -216,6 +216,9 @@ static bool read_dcm_upload_flag(void) break; } } +#ifndef L2_TEST_ENABLED + sleep(60); +#endif fclose(fp); return upload_enabled; From b2b27f18e508d4817ef12b58e36f4b37fa59ced9 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 15:08:51 +0530 Subject: [PATCH 022/108] Update strategies.c --- uploadstblogs/src/strategies.c | 51 +++++----------------------------- 1 file changed, 7 insertions(+), 44 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 40bc395a..a904b6dc 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -946,15 +946,10 @@ static int reboot_archive(RuntimeContext* ctx, SessionState* session) */ static int reboot_upload(RuntimeContext* ctx, SessionState* session) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] REBOOT/NON_DCM: Starting upload phase\n", __FUNCTION__, __LINE__); - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] UploadOnReboot set to %s\n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false"); - - // Check reboot reason and RFC settings (matches script logic) - // Script: if [ "$uploadLog" == "true" ] || [ -z "$reboot_reason" -a "$DISABLE_UPLOAD_LOGS_UNSHEDULED_REBOOT" == "false" ] - // Note: When DCM_FLAG=0 (Non-DCM), script ALWAYS passes "true" regardless of UploadOnReboot value - // When DCM_FLAG=1 (DCM mode), upload_on_reboot determines the behavior bool should_upload = false; + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting upload phase\n", __FUNCTION__, __LINE__); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] UploadOnReboot set to %s\n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false"); + const char* reboot_info_path = "/opt/secure/reboot/previousreboot.info"; // Non-DCM mode (DCM_FLAG=0): Always upload (script line 999: uploadLogOnReboot true) @@ -964,42 +959,10 @@ static int reboot_upload(RuntimeContext* ctx, SessionState* session) "[%s:%d] Non-DCM mode (dcm_flag=0), will always upload logs\n", __FUNCTION__, __LINE__); } - else { - // Check reboot reason file for scheduled reboot (grep -i "Scheduled Reboot\|MAINTENANCE_REBOOT") - bool is_scheduled_reboot = false; - FILE* reboot_file = fopen(reboot_info_path, "r"); - if (reboot_file) { - char line[512]; - while (fgets(line, sizeof(line), reboot_file)) { - // Look for "Scheduled Reboot" or "MAINTENANCE_REBOOT" (case insensitive) - if (strcasestr(line, "Scheduled Reboot") || strcasestr(line, "MAINTENANCE_REBOOT")) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] reboot_reason: %s \n", __FUNCTION__, __LINE__,line); - is_scheduled_reboot = true; - break; - } - } - fclose(reboot_file); - } else { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] Could not open reboot reason file: %s\n", __FUNCTION__, __LINE__, reboot_info_path); - } - - // Get RFC setting for unscheduled reboot upload via RBUS - bool disable_unscheduled_upload = false; - if (!rbus_get_bool_param("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.UploadLogsOnUnscheduledReboot.Disable", - &disable_unscheduled_upload)) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] Failed to get UploadLogsOnUnscheduledReboot.Disable RFC, assuming false\n", - __FUNCTION__, __LINE__); - disable_unscheduled_upload = false; - } - - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] uploadLog:%s and UploadLogsOnUnscheduledReboot.Disable RFC: %s\n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false", disable_unscheduled_upload ? "true" : "false"); - - // Upload if upload_on_reboot is enabled, OR if the reboot is unscheduled - // and the UploadLogsOnUnscheduledReboot.Disable RFC does not disable it. - // Script logic for the unscheduled reboot path: - // [ -z "$reboot_reason" -a "$DISABLE_UPLOAD_LOGS_UNSHEDULED_REBOOT" == "false" ] - if ( ctx->upload_on_reboot==1 || (!is_scheduled_reboot && !disable_unscheduled_upload)) { + else + { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] uploadLog:%s \n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false"); + if ( ctx->upload_on_reboot==1 ) { should_upload = true; } } From 3619dc22bf05d8aee99b2fc120dc38598ba74468 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 15:47:00 +0530 Subject: [PATCH 023/108] Update strategies.c --- uploadstblogs/src/strategies.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index a904b6dc..62a39064 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -950,8 +950,6 @@ static int reboot_upload(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting upload phase\n", __FUNCTION__, __LINE__); RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] UploadOnReboot set to %s\n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false"); - const char* reboot_info_path = "/opt/secure/reboot/previousreboot.info"; - // Non-DCM mode (DCM_FLAG=0): Always upload (script line 999: uploadLogOnReboot true) if (ctx->dcm_flag == 0) { should_upload = true; From 03c2d39a0c5082e137efea7eec69a07e13f93f91 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 21:57:51 +0530 Subject: [PATCH 024/108] Update strategies.c --- uploadstblogs/src/strategies.c | 156 ++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 49 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 62a39064..45684495 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -63,45 +63,13 @@ static int dcm_archive(RuntimeContext* ctx, SessionState* session); static int dcm_upload(RuntimeContext* ctx, SessionState* session); static int dcm_cleanup(RuntimeContext* ctx, SessionState* session, bool upload_success); - - /* ---- Prerequisite sentinel helpers ---- */ -/** - * wait_for_backup_logs - Hard gate: poll for the backup_logs completion sentinel. - * - * Polls BACKUP_LOGS_DONE_FLAG (/tmp/.backup_logs_done) every - * BACKUP_LOGS_POLL_INTERVAL_S seconds for up to BACKUP_LOGS_POLL_TIMEOUT_S seconds. - * - * Returns 0 when the sentinel is present (PreviousLogs/ is complete and safe to read). - * Returns -1 on timeout. The caller MUST abort the reboot upload on -1 — there is - * nothing safe to archive if backup_logs did not complete successfully. - */ -static int wait_for_backup_logs(void) -{ - struct timespec start, now; - struct stat st; - - clock_gettime(CLOCK_MONOTONIC, &start); - - for (;;) { - if (stat(BACKUP_LOGS_DONE_FLAG, &st) == 0) { - return 0; /* backup_logs complete — PreviousLogs/ is safe to read */ - } - - clock_gettime(CLOCK_MONOTONIC, &now); - if ((now.tv_sec - start.tv_sec) >= (time_t)BACKUP_LOGS_POLL_TIMEOUT_S) { - return -1; /* timeout — backup_logs may have failed */ - } - sleep(BACKUP_LOGS_POLL_INTERVAL_S); - } -} - /** * trigger_reboot_info_update - Write trigger sentinel when reboot-reason is absent. * - * Called ONCE at the start of reboot_setup() before the polling loop. - * Writing the trigger file signals update-prev-reboot-info (reboot-manager) to + * Called only after wait_for_reboot_reason() times out. + * Writing the trigger signals update-prev-reboot-info (reboot-manager) to * perform an immediate reboot-reason update within the upload window. * * Cross-repo interface: TRIGGER_REBOOT_INFO_UPDATE consumed by reboot-manager. @@ -122,13 +90,20 @@ static void trigger_reboot_info_update(void) } /** - * wait_for_reboot_reason - Poll for the reboot-reason completion sentinel. + * wait_for_reboot_reason - Wait for the reboot-reason completion sentinel. * - * Polls PATH_FLAG_INVOCATION (/tmp/Update_rebootInfo_invoked) every - * REBOOT_POLL_INTERVAL_S seconds for up to REBOOT_POLL_TIMEOUT_S seconds. + * Uses inotify to watch /tmp for creation of PATH_FLAG_INVOCATION_FILENAME + * ("Update_rebootInfo_invoked"). A select() loop with a 2-second heartbeat + * drives the wait; the total window is bounded by REBOOT_POLL_TIMEOUT_S + * measured on CLOCK_MONOTONIC so EINTR-interrupted sleeps cannot inflate the + * deadline. * - * Uses clock_gettime(CLOCK_MONOTONIC) to measure elapsed time accurately, - * avoiding cumulative drift from EINTR-interrupted sleep() calls. + * A post-watch re-check closes the race window between the initial access() + * call and inotify_add_watch(). + * + * If inotify_init1 or inotify_add_watch fails the function falls back to the + * simple polling path so the upload is never silently blocked by a missing + * kernel feature. * * Returns 0 when the sentinel is present (previousreboot.info is ready). * Returns -1 on timeout. A timeout does NOT abort the upload; the caller @@ -136,24 +111,107 @@ static void trigger_reboot_info_update(void) */ static int wait_for_reboot_reason(void) { - struct timespec start, now; - struct stat st; + /* Fast path: sentinel already present */ + if (access(PATH_FLAG_INVOCATION, F_OK) == 0) { + return 0; + } + + int ifd = inotify_init1(IN_CLOEXEC); + if (ifd < 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, errno); + goto fallback_poll; + } + + int wd = inotify_add_watch(ifd, PATH_FLAG_INVOCATION_DIR, + IN_CREATE | IN_MOVED_TO); + if (wd < 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION_DIR, errno); + close(ifd); + goto fallback_poll; + } - clock_gettime(CLOCK_MONOTONIC, &start); + /* Re-check after watch is set — closes race between access() and add_watch */ + if (access(PATH_FLAG_INVOCATION, F_OK) == 0) { + inotify_rm_watch(ifd, wd); + close(ifd); + return 0; + } - for (;;) { - if (stat(PATH_FLAG_INVOCATION, &st) == 0) { - return 0; /* reboot reason ready */ + { + struct timespec deadline; + if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] clock_gettime failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, errno); + inotify_rm_watch(ifd, wd); + close(ifd); + goto fallback_poll; } + deadline.tv_sec += (time_t)REBOOT_POLL_TIMEOUT_S; + + int found = 0; + char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; + + while (!found) { + struct timespec now; + if (clock_gettime(CLOCK_MONOTONIC, &now) == 0 && + now.tv_sec >= deadline.tv_sec) { + break; /* timeout */ + } + + struct timeval tv = {2, 0}; + fd_set fds; + FD_ZERO(&fds); + FD_SET(ifd, &fds); - clock_gettime(CLOCK_MONOTONIC, &now); - if ((now.tv_sec - start.tv_sec) >= (time_t)REBOOT_POLL_TIMEOUT_S) { - return -1; /* timeout */ + int ret = select(ifd + 1, &fds, NULL, NULL, &tv); + if (ret < 0) { + if (errno == EINTR) { continue; } + break; + } + if (ret == 0) { continue; } /* heartbeat — re-check deadline */ + + ssize_t len = read(ifd, buf, sizeof(buf)); + if (len <= 0) { continue; } + + ssize_t offset = 0; + while (offset < len) { + struct inotify_event *ev = + (struct inotify_event *)(buf + offset); + if (ev->len > 0 && + strcmp(ev->name, PATH_FLAG_INVOCATION_FILENAME) == 0) { + found = 1; + break; + } + offset += (ssize_t)(sizeof(struct inotify_event) + ev->len); + } + } + + inotify_rm_watch(ifd, wd); + close(ifd); + return found ? 0 : -1; + } + +fallback_poll: + { + struct timespec start, now; + clock_gettime(CLOCK_MONOTONIC, &start); + for (;;) { + if (access(PATH_FLAG_INVOCATION, F_OK) == 0) { return 0; } + clock_gettime(CLOCK_MONOTONIC, &now); + if ((now.tv_sec - start.tv_sec) >= (time_t)REBOOT_POLL_TIMEOUT_S) { + return -1; + } + sleep(REBOOT_POLL_INTERVAL_S); } - sleep(REBOOT_POLL_INTERVAL_S); } } + /** * set_upload_annotation - Record a prerequisite-failure annotation in the session. * From 0277a237fe494a7653d20ef8a1ca9ecff7dbb9cc Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 21:59:44 +0530 Subject: [PATCH 025/108] Update strategies.c --- uploadstblogs/src/strategies.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 45684495..d707aa35 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -852,7 +852,7 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) "Writing trigger to request immediate update.\n", __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); trigger_reboot_info_update(); - set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); + session->upload_annotations |= (1 << ANNOTATION_REBOOT_REASON_UNAVAILABLE); } else { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", From cc9bb27c6b3e1985876b662982a1f917c4aaa239 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 16 Jun 2026 22:01:35 +0530 Subject: [PATCH 026/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 27 ++++----------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index c02048de..8016c368 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -51,29 +51,14 @@ All sentinels are volatile /tmp files; cleared automatically on every reboot. ========================== */ -/** backup_logs completion sentinel — written by the backup_logs binary after a - * successful backup_logs_execute(). - * Hard gate: if absent at upload time, PreviousLogs/ is incomplete and the reboot - * upload is aborted (nothing safe to archive). - * Cross-repo interface: path is also defined in backup_logs/include/backup_logs.h. - * Any change MUST be coordinated with the reboot-manager and telemetry repositories. */ -#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" - -/** Poll interval and timeout for the backup_logs hard-gate sentinel. The timeout is - * intentionally shorter than REBOOT_POLL_TIMEOUT_S; if backup_logs hasn't finished - * within this window it is considered failed and the upload is aborted. */ -#define BACKUP_LOGS_POLL_INTERVAL_S 1u -#ifdef GTEST_ENABLE -#define BACKUP_LOGS_POLL_TIMEOUT_S 2u -#else -#define BACKUP_LOGS_POLL_TIMEOUT_S 60u -#endif - /** Reboot reason completion sentinel — written by update-prev-reboot-info (reboot-manager). * Presence guarantees /opt/secure/reboot/previousreboot.info is written and complete. * Cross-repo interface: path is also defined in reboot-manager. * Any change MUST be coordinated with the reboot-manager repository. */ #define PATH_FLAG_INVOCATION "/tmp/Update_rebootInfo_invoked" +/** Directory and filename split used by inotify_add_watch() in strategies.c. */ +#define PATH_FLAG_INVOCATION_DIR "/tmp" +#define PATH_FLAG_INVOCATION_FILENAME "Update_rebootInfo_invoked" /** Trigger file written by uploadstblogs when PATH_FLAG_INVOCATION is absent at upload * time, signalling reboot-manager to perform an immediate reboot-reason update. @@ -81,16 +66,14 @@ * Any path change MUST be coordinated with reboot-manager. */ #define TRIGGER_REBOOT_INFO_UPDATE "/tmp/.trigger_reboot_info_update" -/** Poll interval (seconds) for the reboot-reason prerequisite sentinel. */ -#define REBOOT_POLL_INTERVAL_S 1u - -/** Total poll timeout (seconds) for the reboot-reason prerequisite sentinel. +/** Total wait timeout (seconds) for the reboot-reason prerequisite sentinel. * For unit tests (GTEST_ENABLE) a shorter value avoids multi-minute waits. */ #ifdef GTEST_ENABLE #define REBOOT_POLL_TIMEOUT_S 2u #else #define REBOOT_POLL_TIMEOUT_S 120u #endif +#define REBOOT_POLL_INTERVAL_S 1u /* fallback polling interval */ /** Annotation code set in SessionState when the reboot-reason sentinel times out. * Upload always proceeds; this records that previousreboot.info was unavailable. */ From 21c1acc88e3a20d8a0bea2f03e5e20c09a8a2a7c Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:14:14 +0530 Subject: [PATCH 027/108] Update strategies.c --- uploadstblogs/src/strategies.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index d707aa35..9bbfbd8f 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -39,7 +39,10 @@ #include #include #include +#include #include +#include +#include #include "strategy_handler.h" #include "archive_manager.h" #include "upload_engine.h" From 319b5aab2445f96394869c1fcb1d669946cf4f07 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:04:59 +0530 Subject: [PATCH 028/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 8016c368..1eca2192 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -51,6 +51,19 @@ All sentinels are volatile /tmp files; cleared automatically on every reboot. ========================== */ +#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" + +/** Poll interval and timeout for the backup_logs hard-gate sentinel. The timeout is + * intentionally shorter than REBOOT_POLL_TIMEOUT_S; if backup_logs hasn't finished + * within this window it is considered failed and the upload is aborted. */ +#define BACKUP_LOGS_POLL_INTERVAL_S 1u +#ifdef GTEST_ENABLE +#define BACKUP_LOGS_POLL_TIMEOUT_S 2u +#else +#define BACKUP_LOGS_POLL_TIMEOUT_S 60u +#endif + + /** Reboot reason completion sentinel — written by update-prev-reboot-info (reboot-manager). * Presence guarantees /opt/secure/reboot/previousreboot.info is written and complete. * Cross-repo interface: path is also defined in reboot-manager. From 1c309e5cfc753bef887ca9f64266b8ebc6428063 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:59:36 +0530 Subject: [PATCH 029/108] Update strategies.c --- uploadstblogs/src/strategies.c | 170 ++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 2 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 9bbfbd8f..0b51c22e 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -68,6 +68,172 @@ static int dcm_cleanup(RuntimeContext* ctx, SessionState* session, bool upload_s /* ---- Prerequisite sentinel helpers ---- */ + +/** + * poll_for_sentinel - busy-wait until a file appears or timeout expires. + * Returns 0 when the file exists, -1 on timeout. + */ +static int poll_for_sentinel(const char *path, unsigned int timeout_s, + unsigned int interval_s) +{ + struct timespec start, now; + + if (clock_gettime(CLOCK_MONOTONIC, &start) != 0) { + return (access(path, F_OK) == 0) ? 0 : -1; + } + do { + if (access(path, F_OK) == 0) { + return 0; + } + sleep(interval_s); + clock_gettime(CLOCK_MONOTONIC, &now); + } while ((now.tv_sec - start.tv_sec) < (time_t)timeout_s); + + return (access(path, F_OK) == 0) ? 0 : -1; +} + +/** + * wait_for_backup_logs_done - inotify-based wait for backup_logs completion sentinel. + * + * Blocks until BACKUP_LOGS_DONE_FLAG (/tmp/.backup_logs_done) is created or + * BACKUP_LOGS_SYNC_TIMEOUT_S seconds elapse. Uses inotify so the process wakes + * immediately when the file appears rather than burning CPU on a spin-poll. + * + * A post-watch re-check after inotify_add_watch closes the race window between + * the initial access() fast-path and the watch becoming active. + * + * Falls back to a plain poll-sleep loop if inotify_init1 or inotify_add_watch + * fails (missing kernel support, resource exhaustion, etc.). + * + * This is a **soft gate**: on timeout the caller logs a warning and continues + * so that reboot-manager always produces previousreboot.info, even if + * PreviousLogs/ is not yet fully populated. + */ +static void wait_for_backup_logs_done(void) +{ + /* Fast path: sentinel already written by backup_logs */ + if (access(BACKUP_LOGS_DONE_FLAG, F_OK) == 0) { + RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", + "[%s:%d] backup_logs sentinel already present\n", + __FUNCTION__, __LINE__); + return; + } + + RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", + "[%s:%d] Waiting up to %us for backup_logs sentinel %s\n", + __FUNCTION__, __LINE__, + BACKUP_LOGS_SYNC_TIMEOUT_S, BACKUP_LOGS_DONE_FLAG); + + int ifd = inotify_init1(IN_CLOEXEC); + if (ifd < 0) { + RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", + "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, errno); + goto fallback_poll; + } + + { + int wd = inotify_add_watch(ifd, BACKUP_LOGS_DONE_DIR, + IN_CREATE | IN_MOVED_TO); + if (wd < 0) { + RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", + "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_DIR, errno); + close(ifd); + goto fallback_poll; + } + + /* Re-check after watch is set — closes race between access() and add_watch */ + if (access(BACKUP_LOGS_DONE_FLAG, F_OK) == 0) { + RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", + "[%s:%d] backup_logs sentinel detected (race resolved)\n", + __FUNCTION__, __LINE__); + inotify_rm_watch(ifd, wd); + close(ifd); + return; + } + + struct timespec deadline; + if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0) { + RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", + "[%s:%d] clock_gettime failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, errno); + inotify_rm_watch(ifd, wd); + close(ifd); + goto fallback_poll; + } + deadline.tv_sec += (time_t)BACKUP_LOGS_SYNC_TIMEOUT_S; + + int found = 0; + char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; + + while (!found) { + struct timespec now; + if (clock_gettime(CLOCK_MONOTONIC, &now) == 0 && + now.tv_sec >= deadline.tv_sec) { + break; /* timeout */ + } + + struct timeval tv = {2, 0}; + fd_set fds; + FD_ZERO(&fds); + FD_SET(ifd, &fds); + + int ret = select(ifd + 1, &fds, NULL, NULL, &tv); + if (ret < 0) { + if (errno == EINTR) { continue; } + break; + } + if (ret == 0) { continue; } /* 2 s heartbeat — re-check deadline */ + + ssize_t len = read(ifd, buf, sizeof(buf)); + if (len <= 0) { continue; } + + ssize_t offset = 0; + while (offset < len) { + struct inotify_event *ev = + (struct inotify_event *)(buf + offset); + if (ev->len > 0 && + strcmp(ev->name, BACKUP_LOGS_DONE_FILENAME) == 0) { + found = 1; + break; + } + offset += (ssize_t)(sizeof(struct inotify_event) + ev->len); + } + } + + inotify_rm_watch(ifd, wd); + close(ifd); + + if (found) { + RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", + "[%s:%d] backup_logs sentinel detected\n", + __FUNCTION__, __LINE__); + } else { + RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", + "[%s:%d] backup_logs sentinel absent after %us; " + "PreviousLogs/ may be incomplete\n", + __FUNCTION__, __LINE__, BACKUP_LOGS_SYNC_TIMEOUT_S); + } + return; + } + +fallback_poll: + { + if (poll_for_sentinel(BACKUP_LOGS_DONE_FLAG, + BACKUP_LOGS_SYNC_TIMEOUT_S, 1u) == 0) { + RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", + "[%s:%d] backup_logs sentinel detected (poll)\n", + __FUNCTION__, __LINE__); + } else { + RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", + "[%s:%d] backup_logs sentinel absent after %us (poll); " + "PreviousLogs/ may be incomplete\n", + __FUNCTION__, __LINE__, BACKUP_LOGS_SYNC_TIMEOUT_S); + } + } +} + /** * trigger_reboot_info_update - Write trigger sentinel when reboot-reason is absent. * @@ -813,7 +979,7 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) "[%s:%d] Waiting for backup_logs sentinel %s (timeout %us)\n", __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_FLAG, BACKUP_LOGS_POLL_TIMEOUT_S); - if (wait_for_backup_logs() != 0) { + if (wait_for_backup_logs_done() != 0) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] backup_logs sentinel not present after %us. " "PreviousLogs/ may be incomplete. Aborting reboot upload.\n", @@ -855,7 +1021,7 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) "Writing trigger to request immediate update.\n", __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); trigger_reboot_info_update(); - session->upload_annotations |= (1 << ANNOTATION_REBOOT_REASON_UNAVAILABLE); + set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); } else { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", From 34fdff3b8f1df3b868227e4c74fd8cec7b79e253 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 13:22:04 +0530 Subject: [PATCH 030/108] Update strategies.c --- uploadstblogs/src/strategies.c | 49 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 0b51c22e..34f9bb6c 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1006,30 +1006,6 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) return -1; } - // Wait for reboot reason sentinel. - // Poll first — update-prev-reboot-info normally runs at boot and should already - // be done by now. Only if the sentinel is still absent after the full timeout - // do we write the trigger file to nudge reboot-manager into a retry. - { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", - __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); - - if (wait_for_reboot_reason() != 0) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] Reboot reason sentinel not present after %us. " - "Writing trigger to request immediate update.\n", - __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); - trigger_reboot_info_update(); - set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); - } else { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", - __FUNCTION__, __LINE__); - } - /* Always proceed — backup_logs succeeded; upload must occur */ - } - // Clean up old log backup directories (older than 3 days) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Cleaning old log backup directories (3+ days)\n", __FUNCTION__, __LINE__); int removed_dirs = cleanup_old_log_backups(ctx->log_path, 3); @@ -1357,10 +1333,33 @@ static int reboot_cleanup(RuntimeContext* ctx, SessionState* session, bool uploa "[%s:%d] Failed to move some files to permanent backup\n", __FUNCTION__, __LINE__); } - + // Clean PREV_LOG_PATH RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Cleaning PREV_LOG_PATH\n", __FUNCTION__, __LINE__); + + // Wait for reboot reason sentinel. + // Poll first — update-prev-reboot-info normally runs at boot and should already + // be done by now. Only if the sentinel is still absent after the full timeout + // do we write the trigger file to nudge reboot-manager into a retry. + { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", + __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); + + if (wait_for_reboot_reason() != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] Reboot reason sentinel not present after %us. " + "Writing trigger to request immediate update.\n", + __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); + trigger_reboot_info_update(); + set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); + } else { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", + __FUNCTION__, __LINE__); + } + } clean_directory(ctx->prev_log_path); From cda70a32a44bc1fa51005efe9717368fc80f37d3 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:21:14 +0530 Subject: [PATCH 031/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 1eca2192..98adfc24 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -51,16 +51,15 @@ All sentinels are volatile /tmp files; cleared automatically on every reboot. ========================== */ -#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" +#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" +/** Directory and filename split required by inotify_add_watch(). */ +#define BACKUP_LOGS_DONE_DIR "/tmp" +#define BACKUP_LOGS_DONE_FILENAME ".backup_logs_done" -/** Poll interval and timeout for the backup_logs hard-gate sentinel. The timeout is - * intentionally shorter than REBOOT_POLL_TIMEOUT_S; if backup_logs hasn't finished - * within this window it is considered failed and the upload is aborted. */ -#define BACKUP_LOGS_POLL_INTERVAL_S 1u #ifdef GTEST_ENABLE -#define BACKUP_LOGS_POLL_TIMEOUT_S 2u +# define BACKUP_LOGS_SYNC_TIMEOUT_S 2u #else -#define BACKUP_LOGS_POLL_TIMEOUT_S 60u +# define BACKUP_LOGS_SYNC_TIMEOUT_S 60u #endif From f99e37716702dc3d80435980e72922db15aa41d9 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:48:26 +0530 Subject: [PATCH 032/108] Update strategies.c --- uploadstblogs/src/strategies.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 34f9bb6c..9a9c578d 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -977,13 +977,13 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) // If the sentinel is absent, PreviousLogs/ may be incomplete — abort. RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Waiting for backup_logs sentinel %s (timeout %us)\n", - __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_FLAG, BACKUP_LOGS_POLL_TIMEOUT_S); + __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_FLAG, BACKUP_LOGS_SYNC_TIMEOUT_S); if (wait_for_backup_logs_done() != 0) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] backup_logs sentinel not present after %us. " "PreviousLogs/ may be incomplete. Aborting reboot upload.\n", - __FUNCTION__, __LINE__, BACKUP_LOGS_POLL_TIMEOUT_S); + __FUNCTION__, __LINE__, BACKUP_LOGS_SYNC_TIMEOUT_S); return -1; } From a3bb685823ea94066669d8a00032d8d0e9fcc128 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 15:32:58 +0530 Subject: [PATCH 033/108] Update strategies.c --- uploadstblogs/src/strategies.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 9a9c578d..b57f40de 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -979,13 +979,7 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) "[%s:%d] Waiting for backup_logs sentinel %s (timeout %us)\n", __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_FLAG, BACKUP_LOGS_SYNC_TIMEOUT_S); - if (wait_for_backup_logs_done() != 0) { - RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, - "[%s:%d] backup_logs sentinel not present after %us. " - "PreviousLogs/ may be incomplete. Aborting reboot upload.\n", - __FUNCTION__, __LINE__, BACKUP_LOGS_SYNC_TIMEOUT_S); - return -1; - } + wait_for_backup_logs_done(); RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] backup_logs sentinel detected. PreviousLogs/ is complete.\n", From 670355dbd83eeab836f90f6cb0a84dfda8e3320d Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 21:08:40 +0530 Subject: [PATCH 034/108] Update strategies.c --- uploadstblogs/src/strategies.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index b57f40de..ebd8ddd3 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -443,9 +443,7 @@ static bool read_dcm_upload_flag(void) break; } } -#ifndef L2_TEST_ENABLED - sleep(60); -#endif + fclose(fp); return upload_enabled; @@ -553,7 +551,9 @@ static int dcm_archive(RuntimeContext* ctx, SessionState* session) } RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] DCM: Archive phase complete\n", __FUNCTION__, __LINE__); - +#ifndef L2_TEST_ENABLED + sleep(60); +#endif return 0; } From ec3ca10b290657778cdd647640d96e51aa5c9453 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 21:17:40 +0530 Subject: [PATCH 035/108] Update strategies.c --- uploadstblogs/src/strategies.c | 220 ++++----------------------------- 1 file changed, 21 insertions(+), 199 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index ebd8ddd3..6b16544c 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -68,172 +68,6 @@ static int dcm_cleanup(RuntimeContext* ctx, SessionState* session, bool upload_s /* ---- Prerequisite sentinel helpers ---- */ - -/** - * poll_for_sentinel - busy-wait until a file appears or timeout expires. - * Returns 0 when the file exists, -1 on timeout. - */ -static int poll_for_sentinel(const char *path, unsigned int timeout_s, - unsigned int interval_s) -{ - struct timespec start, now; - - if (clock_gettime(CLOCK_MONOTONIC, &start) != 0) { - return (access(path, F_OK) == 0) ? 0 : -1; - } - do { - if (access(path, F_OK) == 0) { - return 0; - } - sleep(interval_s); - clock_gettime(CLOCK_MONOTONIC, &now); - } while ((now.tv_sec - start.tv_sec) < (time_t)timeout_s); - - return (access(path, F_OK) == 0) ? 0 : -1; -} - -/** - * wait_for_backup_logs_done - inotify-based wait for backup_logs completion sentinel. - * - * Blocks until BACKUP_LOGS_DONE_FLAG (/tmp/.backup_logs_done) is created or - * BACKUP_LOGS_SYNC_TIMEOUT_S seconds elapse. Uses inotify so the process wakes - * immediately when the file appears rather than burning CPU on a spin-poll. - * - * A post-watch re-check after inotify_add_watch closes the race window between - * the initial access() fast-path and the watch becoming active. - * - * Falls back to a plain poll-sleep loop if inotify_init1 or inotify_add_watch - * fails (missing kernel support, resource exhaustion, etc.). - * - * This is a **soft gate**: on timeout the caller logs a warning and continues - * so that reboot-manager always produces previousreboot.info, even if - * PreviousLogs/ is not yet fully populated. - */ -static void wait_for_backup_logs_done(void) -{ - /* Fast path: sentinel already written by backup_logs */ - if (access(BACKUP_LOGS_DONE_FLAG, F_OK) == 0) { - RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", - "[%s:%d] backup_logs sentinel already present\n", - __FUNCTION__, __LINE__); - return; - } - - RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", - "[%s:%d] Waiting up to %us for backup_logs sentinel %s\n", - __FUNCTION__, __LINE__, - BACKUP_LOGS_SYNC_TIMEOUT_S, BACKUP_LOGS_DONE_FLAG); - - int ifd = inotify_init1(IN_CLOEXEC); - if (ifd < 0) { - RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", - "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, errno); - goto fallback_poll; - } - - { - int wd = inotify_add_watch(ifd, BACKUP_LOGS_DONE_DIR, - IN_CREATE | IN_MOVED_TO); - if (wd < 0) { - RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", - "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_DIR, errno); - close(ifd); - goto fallback_poll; - } - - /* Re-check after watch is set — closes race between access() and add_watch */ - if (access(BACKUP_LOGS_DONE_FLAG, F_OK) == 0) { - RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", - "[%s:%d] backup_logs sentinel detected (race resolved)\n", - __FUNCTION__, __LINE__); - inotify_rm_watch(ifd, wd); - close(ifd); - return; - } - - struct timespec deadline; - if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0) { - RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", - "[%s:%d] clock_gettime failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, errno); - inotify_rm_watch(ifd, wd); - close(ifd); - goto fallback_poll; - } - deadline.tv_sec += (time_t)BACKUP_LOGS_SYNC_TIMEOUT_S; - - int found = 0; - char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; - - while (!found) { - struct timespec now; - if (clock_gettime(CLOCK_MONOTONIC, &now) == 0 && - now.tv_sec >= deadline.tv_sec) { - break; /* timeout */ - } - - struct timeval tv = {2, 0}; - fd_set fds; - FD_ZERO(&fds); - FD_SET(ifd, &fds); - - int ret = select(ifd + 1, &fds, NULL, NULL, &tv); - if (ret < 0) { - if (errno == EINTR) { continue; } - break; - } - if (ret == 0) { continue; } /* 2 s heartbeat — re-check deadline */ - - ssize_t len = read(ifd, buf, sizeof(buf)); - if (len <= 0) { continue; } - - ssize_t offset = 0; - while (offset < len) { - struct inotify_event *ev = - (struct inotify_event *)(buf + offset); - if (ev->len > 0 && - strcmp(ev->name, BACKUP_LOGS_DONE_FILENAME) == 0) { - found = 1; - break; - } - offset += (ssize_t)(sizeof(struct inotify_event) + ev->len); - } - } - - inotify_rm_watch(ifd, wd); - close(ifd); - - if (found) { - RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", - "[%s:%d] backup_logs sentinel detected\n", - __FUNCTION__, __LINE__); - } else { - RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", - "[%s:%d] backup_logs sentinel absent after %us; " - "PreviousLogs/ may be incomplete\n", - __FUNCTION__, __LINE__, BACKUP_LOGS_SYNC_TIMEOUT_S); - } - return; - } - -fallback_poll: - { - if (poll_for_sentinel(BACKUP_LOGS_DONE_FLAG, - BACKUP_LOGS_SYNC_TIMEOUT_S, 1u) == 0) { - RDK_LOG(RDK_LOG_INFO, "LOG.RDK.REBOOTINFO", - "[%s:%d] backup_logs sentinel detected (poll)\n", - __FUNCTION__, __LINE__); - } else { - RDK_LOG(RDK_LOG_WARN, "LOG.RDK.REBOOTINFO", - "[%s:%d] backup_logs sentinel absent after %us (poll); " - "PreviousLogs/ may be incomplete\n", - __FUNCTION__, __LINE__, BACKUP_LOGS_SYNC_TIMEOUT_S); - } - } -} - /** * trigger_reboot_info_update - Write trigger sentinel when reboot-reason is absent. * @@ -973,17 +807,28 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting setup phase\n", __FUNCTION__, __LINE__); - // Hard gate: wait for backup_logs to complete before touching PreviousLogs/. - // If the sentinel is absent, PreviousLogs/ may be incomplete — abort. - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Waiting for backup_logs sentinel %s (timeout %us)\n", - __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_FLAG, BACKUP_LOGS_SYNC_TIMEOUT_S); - - wait_for_backup_logs_done(); + // Wait for reboot reason sentinel. + // Poll first — update-prev-reboot-info normally runs at boot and should already + // be done by now. Only if the sentinel is still absent after the full timeout + // do we write the trigger file to nudge reboot-manager into a retry. + { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", + __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] backup_logs sentinel detected. PreviousLogs/ is complete.\n", - __FUNCTION__, __LINE__); + if (wait_for_reboot_reason() != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] Reboot reason sentinel not present after %us. " + "Writing trigger to request immediate update.\n", + __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); + trigger_reboot_info_update(); + set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); + } else { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", + __FUNCTION__, __LINE__); + } + } // Check if PREV_LOG_PATH exists and has .txt or .log files if (!dir_exists(ctx->prev_log_path)) { @@ -1331,29 +1176,6 @@ static int reboot_cleanup(RuntimeContext* ctx, SessionState* session, bool uploa // Clean PREV_LOG_PATH RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Cleaning PREV_LOG_PATH\n", __FUNCTION__, __LINE__); - - // Wait for reboot reason sentinel. - // Poll first — update-prev-reboot-info normally runs at boot and should already - // be done by now. Only if the sentinel is still absent after the full timeout - // do we write the trigger file to nudge reboot-manager into a retry. - { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", - __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); - - if (wait_for_reboot_reason() != 0) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] Reboot reason sentinel not present after %us. " - "Writing trigger to request immediate update.\n", - __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); - trigger_reboot_info_update(); - set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); - } else { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", - __FUNCTION__, __LINE__); - } - } clean_directory(ctx->prev_log_path); From c7c896c5cbf0fabd729a7384cafa35392f0cf7e7 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 21:19:20 +0530 Subject: [PATCH 036/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 98adfc24..8016c368 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -51,18 +51,6 @@ All sentinels are volatile /tmp files; cleared automatically on every reboot. ========================== */ -#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" -/** Directory and filename split required by inotify_add_watch(). */ -#define BACKUP_LOGS_DONE_DIR "/tmp" -#define BACKUP_LOGS_DONE_FILENAME ".backup_logs_done" - -#ifdef GTEST_ENABLE -# define BACKUP_LOGS_SYNC_TIMEOUT_S 2u -#else -# define BACKUP_LOGS_SYNC_TIMEOUT_S 60u -#endif - - /** Reboot reason completion sentinel — written by update-prev-reboot-info (reboot-manager). * Presence guarantees /opt/secure/reboot/previousreboot.info is written and complete. * Cross-repo interface: path is also defined in reboot-manager. From 7cb88eaea7d849e763b1b9b3fb85838cfd9793b5 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 22:57:21 +0530 Subject: [PATCH 037/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 8016c368..e15a4f55 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -79,6 +79,27 @@ * Upload always proceeds; this records that previousreboot.info was unavailable. */ #define ANNOTATION_REBOOT_REASON_UNAVAILABLE 1 + * Presence at upload time means the system clock is accurate; absence means the + * device rebooted without receiving NTP, and an internet check + last-known-good + * time fallback should be attempted. + * Cross-repo interface: path matches STT_FLAG in systimemgr and reboot-manager. */ +#define STT_FLAG "/tmp/stt_received" + +/** Telemetry PreviousLogs scan completion sentinel — written by telemetry after it + * finishes grepping PreviousLogs. Consumed by uploadstblogs as an optional gate. + * Cross-repo interface: any path change MUST be coordinated with telemetry. */ +#define TELEMETRY_PREVLOGS_DONE_FLAG "/tmp/.telemetry_prevlogs_done" + +/** Annotation code set in SessionState when NTP was not synced at upload time and + * internet connectivity was absent, so the last-known-good time fallback could not + * be applied. Upload always proceeds. */ +#define ANNOTATION_NTP_UNAVAILABLE 2 + +/** Path to the last-known-good clock file maintained by systimemgr (RdkDefaultTimeSync). + * Contains a plain epoch-seconds integer written by systimemgr on every successful + * time update. Read directly in strategies.c when NTP is absent but internet is up. + * Cross-repo interface: path matches RdkDefaultTimeSync default in systimemgr. */ +#define SYSTIMEMGR_CLOCK_FILE "/opt/secure/clock.txt" /* ========================== Enumerations From d9f073477e05c372bf3aa700474a04ba0a6e73e5 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 23:06:27 +0530 Subject: [PATCH 038/108] Update strategies.c --- uploadstblogs/src/strategies.c | 158 +++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 6b16544c..316f503c 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -36,13 +36,16 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include +#include #include "strategy_handler.h" #include "archive_manager.h" #include "upload_engine.h" @@ -66,6 +69,134 @@ static int dcm_archive(RuntimeContext* ctx, SessionState* session); static int dcm_upload(RuntimeContext* ctx, SessionState* session); static int dcm_cleanup(RuntimeContext* ctx, SessionState* session, bool upload_success); + + +#define THUNDER_JSONRPC_URL "http://127.0.0.1:9998/jsonrpc" +#define INTERNET_CHECK_TIMEOUT_S 5L + +typedef struct { + char buf[512]; + size_t len; +} rpc_resp_t; + +static size_t internet_write_cb(void *ptr, size_t size, size_t nmemb, void *userp) +{ + rpc_resp_t *r = (rpc_resp_t *)userp; + size_t incoming = size * nmemb; + size_t space = sizeof(r->buf) - r->len - 1u; + if (incoming > space) { incoming = space; } + memcpy(r->buf + r->len, ptr, incoming); + r->len += incoming; + r->buf[r->len] = '\0'; + return size * nmemb; +} + +static bool nm_query_ipver(const char *ipversion) +{ + char payload[256]; + CURL *ch; + rpc_resp_t resp; + struct curl_slist *hdrs = NULL; + CURLcode rc; + int n; + + n = snprintf(payload, sizeof(payload), + "{\"jsonrpc\":\"2.0\",\"id\":\"42\"," + "\"method\":\"org.rdk.NetworkManager.IsConnectedToInternet\"," + "\"params\":{\"ipversion\":\"%s\"}}", ipversion); + if (n < 0 || (size_t)n >= sizeof(payload)) { return false; } + + ch = curl_easy_init(); + if (!ch) { return false; } + + memset(&resp, 0, sizeof(resp)); + hdrs = curl_slist_append(NULL, "Content-Type: application/json"); + if (!hdrs) { curl_easy_cleanup(ch); return false; } + + curl_easy_setopt(ch, CURLOPT_URL, THUNDER_JSONRPC_URL); + curl_easy_setopt(ch, CURLOPT_POSTFIELDS, payload); + curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hdrs); + curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, internet_write_cb); + curl_easy_setopt(ch, CURLOPT_WRITEDATA, &resp); + curl_easy_setopt(ch, CURLOPT_TIMEOUT, INTERNET_CHECK_TIMEOUT_S); + curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L); + + rc = curl_easy_perform(ch); + curl_slist_free_all(hdrs); + curl_easy_cleanup(ch); + + if (rc != CURLE_OK) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] NetworkManager RPC (%s) failed: %s\n", + __FUNCTION__, __LINE__, ipversion, curl_easy_strerror(rc)); + return false; + } + + /* status != "NO_INTERNET" means connected */ + return (strstr(resp.buf, "NO_INTERNET") == NULL); +} + +static bool check_internet_connectivity(void) +{ + /* Try IPv4 first; fall back to IPv6 — mirrors iarmInterface.c */ + if (nm_query_ipver("IPv4")) { return true; } + return nm_query_ipver("IPv6"); +} + + +/** + * apply_ntp_fallback_time - Apply last-known-good time from systimemgr via RBUS. + * + * Called when STT_FLAG is absent but internet connectivity is available. + * Reads SYSTIMEMGR_RBUS_LAST_TIME (epoch seconds string) and sets the system + * clock via settimeofday(). Non-fatal: a warning is logged on any failure + * and the upload continues with the existing system time. + */ +static void apply_ntp_fallback_time(void) +{ + char time_buf[32] = {0}; + long epoch; + struct timeval tv; + FILE *fp; + + fp = fopen(SYSTIMEMGR_CLOCK_FILE, "r"); + if (!fp) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] systimemgr clock file %s not readable (errno=%d)\n", + __FUNCTION__, __LINE__, SYSTIMEMGR_CLOCK_FILE, errno); + return; + } + if (fgets(time_buf, (int)sizeof(time_buf), fp) == NULL) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] systimemgr clock file %s is empty\n", + __FUNCTION__, __LINE__, SYSTIMEMGR_CLOCK_FILE); + fclose(fp); + return; + } + fclose(fp); + + epoch = strtol(time_buf, NULL, 10); + if (epoch <= 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] systimemgr returned invalid epoch string: '%s'\n", + __FUNCTION__, __LINE__, time_buf); + return; + } + + tv.tv_sec = (time_t)epoch; + tv.tv_usec = 0; + if (settimeofday(&tv, NULL) != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] settimeofday(%ld) failed (errno=%d)\n", + __FUNCTION__, __LINE__, epoch, errno); + return; + } + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Applied last-known-good time epoch=%ld from systimemgr\n", + __FUNCTION__, __LINE__, epoch); +} + /* ---- Prerequisite sentinel helpers ---- */ /** @@ -807,6 +938,33 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting setup phase\n", __FUNCTION__, __LINE__); + /* NTP sync check (REQ-SYNC-002). + * If STT_FLAG is absent the system clock was not set from NTP this boot. + * In that case query the network stack: if internet is reachable the clock + * is probably ahead of epoch so we retrieve the last-known-good time from + * systimemgr (via RBUS) and apply it with settimeofday(). This ensures + * archive timestamps are meaningful even without NTP. + * If internet is not reachable we annotate the session and continue — the + * upload must not be blocked by a missing time source. */ + { + struct stat st_ntp; + if (stat(STT_FLAG, &st_ntp) != 0) { + bool connected = check_internet_connectivity(); + + if (connected) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] NTP absent but internet available; applying last-known-good time\n", + __FUNCTION__, __LINE__); + apply_ntp_fallback_time(); + } else { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] NTP absent and no internet; proceeding with current system time\n", + __FUNCTION__, __LINE__); + session->upload_annotations |= (1 << ANNOTATION_NTP_UNAVAILABLE); + } + } + } + // Wait for reboot reason sentinel. // Poll first — update-prev-reboot-info normally runs at boot and should already // be done by now. Only if the sentinel is still absent after the full timeout From ccd4cf8ec664f44058626a8a3feb312775c5b88b Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 17 Jun 2026 23:44:47 +0530 Subject: [PATCH 039/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index e15a4f55..9e727822 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -79,6 +79,7 @@ * Upload always proceeds; this records that previousreboot.info was unavailable. */ #define ANNOTATION_REBOOT_REASON_UNAVAILABLE 1 +/** NTP sync completion sentinel — written by systimemgr when NTP is synchronised. * Presence at upload time means the system clock is accurate; absence means the * device rebooted without receiving NTP, and an internet check + last-known-good * time fallback should be attempted. From 994f21306ba8b6755b85b96e846987ba48d6ee2d Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:21:33 +0530 Subject: [PATCH 040/108] Update strategies.c --- uploadstblogs/src/strategies.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 316f503c..30b0b006 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -938,6 +938,21 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting setup phase\n", __FUNCTION__, __LINE__); + /* backup_logs gate (REQ-SYNC-001). + * backup_logs writes BACKUP_LOGS_DONE_FLAG when PreviousLogs are fully assembled. + * telemetry already waited for this sentinel before grepping PreviousLogs, so it + * should be present by now. If absent, the log set is incomplete — abort and let + * the next scheduled upload attempt pick it up once backup_logs finishes. */ + { + struct stat st_bl; + if (stat(BACKUP_LOGS_DONE_FLAG, &st_bl) != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] backup_logs not done (%s absent); aborting upload\n", + __FUNCTION__, __LINE__, BACKUP_LOGS_DONE_FLAG); + return -1; + } + } + /* NTP sync check (REQ-SYNC-002). * If STT_FLAG is absent the system clock was not set from NTP this boot. * In that case query the network stack: if internet is reachable the clock From 4aee529618dcc3e42edf90bf5964ecce1105dcec Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:23:49 +0530 Subject: [PATCH 041/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 9e727822..2d409748 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -51,6 +51,14 @@ All sentinels are volatile /tmp files; cleared automatically on every reboot. ========================== */ +/** backup_logs completion sentinel — written by backup_logs (dcm-agent) after + * PreviousLogs have been fully assembled. Presence guarantees the log set is + * stable and ready for upload. Absence means backup_logs has not finished; + * reboot_setup() must abort so the upload is not attempted on an incomplete set. + * Cross-repo interface: path is also defined in dcm-agent/backup_logs. + * Any change MUST be coordinated with the backup_logs module. */ +#define BACKUP_LOGS_DONE_FLAG "/tmp/.backup_logs_done" + /** Reboot reason completion sentinel — written by update-prev-reboot-info (reboot-manager). * Presence guarantees /opt/secure/reboot/previousreboot.info is written and complete. * Cross-repo interface: path is also defined in reboot-manager. From b607a6c68bb9719e26a588fcb53e91130bc8a384 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:23:50 +0530 Subject: [PATCH 042/108] Update strategies.c --- uploadstblogs/src/strategies.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 30b0b006..c8bb6daf 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -200,25 +200,26 @@ static void apply_ntp_fallback_time(void) /* ---- Prerequisite sentinel helpers ---- */ /** - * trigger_reboot_info_update - Write trigger sentinel when reboot-reason is absent. + * trigger_reboot_info_update - Touch STT_FLAG to trigger reboot-reason update. * * Called only after wait_for_reboot_reason() times out. - * Writing the trigger signals update-prev-reboot-info (reboot-manager) to - * perform an immediate reboot-reason update within the upload window. + * Touching STT_FLAG (/tmp/stt_received) signals update-prev-reboot-info + * (reboot-manager) to perform an immediate reboot-reason update; reboot-manager + * watches STT_FLAG as its primary gate to run update_reboot_info(). * - * Cross-repo interface: TRIGGER_REBOOT_INFO_UPDATE consumed by reboot-manager. + * Cross-repo interface: STT_FLAG is watched by reboot-manager. */ static void trigger_reboot_info_update(void) { struct stat st; if (stat(PATH_FLAG_INVOCATION, &st) != 0) { - int fd = open(TRIGGER_REBOOT_INFO_UPDATE, O_CREAT | O_WRONLY | O_TRUNC, 0644); + int fd = open(STT_FLAG, O_CREAT | O_WRONLY, 0644); if (fd >= 0) { close(fd); RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Wrote reboot reason trigger: %s\n", - __FUNCTION__, __LINE__, TRIGGER_REBOOT_INFO_UPDATE); + "[%s:%d] Touched STT_FLAG to trigger reboot reason update: %s\n", + __FUNCTION__, __LINE__, STT_FLAG); } } } From d6cf03520450e19a9625033f078442a6053c58cc Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 22:06:23 +0530 Subject: [PATCH 043/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 2d409748..04cd00d7 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -356,6 +356,7 @@ typedef struct { bool success; /**< Overall success status */ char archive_file[MAX_FILENAME_LENGTH]; /**< Generated archive filename */ int upload_annotations; /**< Bitmask of ANNOTATION_* codes set during prerequisite fallback */ + time_t archive_ref_time; /**< Reference time for archive filename (0 = use system time) */ } SessionState; /* ========================== From fad40b3aec68c2d60dd1450ad0f01ab32f4ec6ed Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 22:15:23 +0530 Subject: [PATCH 044/108] Update strategies.c --- uploadstblogs/src/strategies.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index c8bb6daf..70a11054 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -145,18 +145,19 @@ static bool check_internet_connectivity(void) /** - * apply_ntp_fallback_time - Apply last-known-good time from systimemgr via RBUS. + * apply_ntp_fallback_time - Read last-known-good epoch from systimemgr clock file. * * Called when STT_FLAG is absent but internet connectivity is available. - * Reads SYSTIMEMGR_RBUS_LAST_TIME (epoch seconds string) and sets the system - * clock via settimeofday(). Non-fatal: a warning is logged on any failure - * and the upload continues with the existing system time. + * Returns the epoch seconds read from SYSTIMEMGR_CLOCK_FILE so the caller can + * embed it directly in the archive filename via ctx->archive_ref_time. + * Does NOT modify the system clock. + * + * Returns the epoch (> 0) on success, 0 on any failure. */ -static void apply_ntp_fallback_time(void) +static time_t apply_ntp_fallback_time(void) { char time_buf[32] = {0}; long epoch; - struct timeval tv; FILE *fp; fp = fopen(SYSTIMEMGR_CLOCK_FILE, "r"); @@ -164,14 +165,14 @@ static void apply_ntp_fallback_time(void) RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] systimemgr clock file %s not readable (errno=%d)\n", __FUNCTION__, __LINE__, SYSTIMEMGR_CLOCK_FILE, errno); - return; + return 0; } if (fgets(time_buf, (int)sizeof(time_buf), fp) == NULL) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] systimemgr clock file %s is empty\n", __FUNCTION__, __LINE__, SYSTIMEMGR_CLOCK_FILE); fclose(fp); - return; + return 0; } fclose(fp); @@ -180,21 +181,13 @@ static void apply_ntp_fallback_time(void) RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] systimemgr returned invalid epoch string: '%s'\n", __FUNCTION__, __LINE__, time_buf); - return; - } - - tv.tv_sec = (time_t)epoch; - tv.tv_usec = 0; - if (settimeofday(&tv, NULL) != 0) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] settimeofday(%ld) failed (errno=%d)\n", - __FUNCTION__, __LINE__, epoch, errno); - return; + return 0; } RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Applied last-known-good time epoch=%ld from systimemgr\n", + "[%s:%d] Using last-known-good time epoch=%ld from systimemgr for archive name\n", __FUNCTION__, __LINE__, epoch); + return (time_t)epoch; } /* ---- Prerequisite sentinel helpers ---- */ @@ -971,7 +964,7 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] NTP absent but internet available; applying last-known-good time\n", __FUNCTION__, __LINE__); - apply_ntp_fallback_time(); + ctx->archive_ref_time = apply_ntp_fallback_time(); } else { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] NTP absent and no internet; proceeding with current system time\n", From 914169218962a9ff2bfa9e11c1e71a73c84c48b0 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 22:22:35 +0530 Subject: [PATCH 045/108] Update archive_manager.c --- uploadstblogs/src/archive_manager.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/uploadstblogs/src/archive_manager.c b/uploadstblogs/src/archive_manager.c index cf5dc3b7..d6253ae0 100755 --- a/uploadstblogs/src/archive_manager.c +++ b/uploadstblogs/src/archive_manager.c @@ -385,6 +385,9 @@ struct tar_header { static int create_archive_with_options(RuntimeContext* ctx, SessionState* session, const char* source_dir, const char* output_dir, const char* prefix); +static bool generate_archive_name_at(char* buffer, size_t buffer_size, + const char* mac_address, const char* prefix, + time_t ref_time); /** * @brief Generate archive filename with MAC and timestamp (script format) @@ -414,16 +417,20 @@ bool generate_archive_name(char* buffer, size_t buffer_size, return false; } - time_t now = time(NULL); + return generate_archive_name_at(buffer, buffer_size, mac_address, prefix, time(NULL)); +} +static bool generate_archive_name_at(char* buffer, size_t buffer_size, + const char* mac_address, const char* prefix, + time_t ref_time) +{ struct tm tm_utc; - if (gmtime_r(&now, &tm_utc) == NULL) { + if (gmtime_r(&ref_time, &tm_utc) == NULL) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Failed to get UTC time\n", __FUNCTION__, __LINE__); return false; } char timestamp[32]; - // Format UTC timestamp as MM-DD-YY-HH-MMAM/PM. if (strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p", &tm_utc) == 0) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Failed to format timestamp\n", __FUNCTION__, __LINE__); @@ -706,8 +713,9 @@ static int create_archive_with_options(RuntimeContext* ctx, SessionState* sessio prefix); char archive_filename[MAX_FILENAME_LENGTH]; - if (!generate_archive_name(archive_filename, sizeof(archive_filename), - ctx->mac_address, prefix)) { + time_t ref_time = (ctx->archive_ref_time != 0) ? ctx->archive_ref_time : time(NULL); + if (!generate_archive_name_at(archive_filename, sizeof(archive_filename), + ctx->mac_address, prefix, ref_time)) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Failed to generate archive filename\n", __FUNCTION__, __LINE__); return -1; From c7b475bb99c65b03538289c5ce802e63595eb6d7 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 23:06:18 +0530 Subject: [PATCH 046/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 04cd00d7..f2e59d2e 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -30,6 +30,7 @@ #define UPLOADSTBLOGS_TYPES_H #include +#include /* ========================== From 74b9808bba59f11e924accb4563eadb7b63937f4 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Thu, 18 Jun 2026 23:18:41 +0530 Subject: [PATCH 047/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index f2e59d2e..06ec9944 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -299,6 +299,7 @@ typedef struct { bool tls_enabled; /**< TLS 1.2 support enabled */ bool maintenance_enabled; /**< Maintenance mode enabled */ bool uploadlogsnow_mode; /**< UploadLogsNow mode enabled */ + time_t archive_ref_time; /**< Reference time for archive filename (0 = use system time) */ // File system paths char log_path[MAX_PATH_LENGTH]; /**< Main log directory */ @@ -357,7 +358,6 @@ typedef struct { bool success; /**< Overall success status */ char archive_file[MAX_FILENAME_LENGTH]; /**< Generated archive filename */ int upload_annotations; /**< Bitmask of ANNOTATION_* codes set during prerequisite fallback */ - time_t archive_ref_time; /**< Reference time for archive filename (0 = use system time) */ } SessionState; /* ========================== From e3b7689032d99c360c64703f5fc2e3e488165f75 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:15:53 +0530 Subject: [PATCH 048/108] Update dcm.c --- dcm.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/dcm.c b/dcm.c index bc48a85b..b999154e 100755 --- a/dcm.c +++ b/dcm.c @@ -84,6 +84,22 @@ static VOID dcmRunJobs(const INT8* profileName, VOID *pHandle) DCMInfo("\nStart log upload via library API\n"); + /* Log wall-clock time and elapsed time since DCM start */ + { + struct timespec now_ts; + clock_gettime(CLOCK_MONOTONIC, &now_ts); + long elapsed_sec = (long)(now_ts.tv_sec - pdcmHandle->start_time.tv_sec); + long elapsed_msec = (now_ts.tv_nsec - pdcmHandle->start_time.tv_nsec) / 1000000L; + if (elapsed_msec < 0) { elapsed_sec--; elapsed_msec += 1000L; } + + time_t wall = time(NULL); + struct tm *tm_info = localtime(&wall); + char wall_ts[32]; + strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); + DCMInfo("Log upload start wall-clock time: %s (elapsed since DCM start: %lds %ldms)\n", + wall_ts, elapsed_sec, elapsed_msec); + } + // Call uploadstblogs library API instead of shell script UploadSTBLogsParams params = { .flag = 0, @@ -97,6 +113,21 @@ static VOID dcmRunJobs(const INT8* profileName, VOID *pHandle) }; #ifndef GTEST_ENABLE int result = uploadstblogs_run(¶ms); + { + struct timespec done_ts; + clock_gettime(CLOCK_MONOTONIC, &done_ts); + long upload_sec = (long)(done_ts.tv_sec - pdcmHandle->start_time.tv_sec); + long upload_msec = (done_ts.tv_nsec - pdcmHandle->start_time.tv_nsec) / 1000000L; + if (upload_msec < 0) { upload_sec--; upload_msec += 1000L; } + if (result != 0) { + DCMError("Log upload failed with error code: %d (elapsed since DCM start: %lds %ldms)\n", + result, upload_sec, upload_msec); + } else { + DCMInfo("Log upload completed successfully (elapsed since DCM start: %lds %ldms)\n", + upload_sec, upload_msec); + } + } + if (result != 0) { DCMError("Log upload failed with error code: %d\n", result); } else { @@ -279,6 +310,15 @@ int main(int argc, char* argv[]) g_pdcmHandle->isDebugEnabled = true; DCMInfo("Starting DCM Process: %d\n", getpid()); + /* Record monotonic start time for elapsed-time measurements */ + clock_gettime(CLOCK_MONOTONIC, &g_pdcmHandle->start_time); + { + time_t now = time(NULL); + struct tm *tm_info = localtime(&now); + char wall_ts[32]; + strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); + DCMInfo("DCM start wall-clock time: %s\n", wall_ts); + } /* Create child process */ process_id = fork(); From a9275a6391b6ce879db230a81fa6539416eea15d Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:26:51 +0530 Subject: [PATCH 049/108] Update backup_logs.c --- backup_logs/src/backup_logs.c | 56 +++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/backup_logs/src/backup_logs.c b/backup_logs/src/backup_logs.c index 2c607162..b1114794 100644 --- a/backup_logs/src/backup_logs.c +++ b/backup_logs/src/backup_logs.c @@ -35,6 +35,7 @@ #include #include #include +#include #define BACKUP_LOGS_VERSION "1.0.0" #define BACKUP_LOGS_BUILD_DATE __DATE__ @@ -278,6 +279,17 @@ int backup_logs_main(int argc, char *argv[]) { static backup_config_t config; memset(&config, 0, sizeof(config)); + /* Record monotonic start time for elapsed-time measurements */ + struct timespec start_time; + clock_gettime(CLOCK_MONOTONIC, &start_time); + { + time_t now = time(NULL); + struct tm *tm_info = localtime(&now); + char wall_ts[32]; + strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); + RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "backup_logs start wall-clock time: %s\n", wall_ts); + } + /* Initialize backup system */ RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Initializing backup system\n"); result = backup_logs_init(&config); @@ -287,6 +299,22 @@ int backup_logs_main(int argc, char *argv[]) { } /* Execute backup process */ + + { + struct timespec exec_ts; + clock_gettime(CLOCK_MONOTONIC, &exec_ts); + long el_sec = (long)(exec_ts.tv_sec - start_time.tv_sec); + long el_msec = (exec_ts.tv_nsec - start_time.tv_nsec) / 1000000L; + if (el_msec < 0) { el_sec--; el_msec += 1000L; } + time_t wall = time(NULL); + struct tm *tm_info = localtime(&wall); + char wall_ts[32]; + strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); + RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, + "Backup execution start wall-clock time: %s (elapsed since backup_logs start: %lds %ldms)\n", + wall_ts, el_sec, el_msec); + } + RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Starting backup execution\n"); result = backup_logs_execute(&config); if (result != BACKUP_SUCCESS) { @@ -295,6 +323,23 @@ int backup_logs_main(int argc, char *argv[]) { return EXIT_FAILURE; } + { + struct timespec done_ts; + clock_gettime(CLOCK_MONOTONIC, &done_ts); + long el_sec = (long)(done_ts.tv_sec - start_time.tv_sec); + long el_msec = (done_ts.tv_nsec - start_time.tv_nsec) / 1000000L; + if (el_msec < 0) { el_sec--; el_msec += 1000L; } + if (result != BACKUP_SUCCESS) { + RDK_LOG(RDK_LOG_ERROR, LOG_BACKUP_LOGS, + "Backup execution failed with result: %d (elapsed since backup_logs start: %lds %ldms)\n", + result, el_sec, el_msec); + } else { + RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, + "Backup execution completed successfully (elapsed since backup_logs start: %lds %ldms)\n", + el_sec, el_msec); + } + } + /* Cleanup and exit */ RDK_LOG(RDK_LOG_DEBUG, LOG_BACKUP_LOGS, "Starting cleanup and shutdown\n"); result = backup_logs_cleanup(&config); @@ -319,6 +364,17 @@ int backup_logs_main(int argc, char *argv[]) { RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Sentinel written: %s\n", BACKUP_LOGS_DONE_FLAG); } } + + { + struct timespec final_ts; + clock_gettime(CLOCK_MONOTONIC, &final_ts); + long el_sec = (long)(final_ts.tv_sec - start_time.tv_sec); + long el_msec = (final_ts.tv_nsec - start_time.tv_nsec) / 1000000L; + if (el_msec < 0) { el_sec--; el_msec += 1000L; } + RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, + "Backup process completed successfully (total elapsed: %lds %ldms)\n", + el_sec, el_msec); + } return EXIT_SUCCESS; } #ifndef GTEST_ENABLE From a5b80c2ac638d3801d487d0f5486d56489706744 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Fri, 19 Jun 2026 22:20:58 +0530 Subject: [PATCH 050/108] Update dcm.h --- dcm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dcm.h b/dcm.h index e2f4f083..f47cca59 100644 --- a/dcm.h +++ b/dcm.h @@ -40,6 +40,7 @@ typedef struct _dcmdHandle INT8 *pExecBuff; INT8 logCron[16]; INT8 difdCron[16]; + struct timespec start_time; /* Monotonic timestamp at DCM process start */ } DCMDHandle; From 0a3e92249a58feda2ebf153cca212107697c1c04 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 22 Jun 2026 22:34:25 +0530 Subject: [PATCH 051/108] Update context_manager.c --- uploadstblogs/src/context_manager.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/src/context_manager.c b/uploadstblogs/src/context_manager.c index 44d1cdfe..6dae5614 100755 --- a/uploadstblogs/src/context_manager.c +++ b/uploadstblogs/src/context_manager.c @@ -156,12 +156,21 @@ bool init_context(RuntimeContext* ctx) { // Initialize RDK Logger /* Extended initialization with programmatic configuration */ + //RDK Logger Initialisation + rdk_LogOutput_File filelog; + strncpy(filelog.fileName, "dcmscript.log", sizeof(filelog.fileName)-1); + filelog.fileName[sizeof(filelog.fileName) - 1] = '\0'; + strncpy(filelog.fileLocation, "/opt/logs/", sizeof(filelog.fileLocation)-1); + filelog.fileLocation[sizeof(filelog.fileLocation) - 1] = '\0'; + filelog.fileSizeMax = 10240; + filelog.fileCountMax = 1; + rdk_logger_ext_config_t config = { .pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */ .loglevel = RDK_LOG_INFO, /* Default log level */ .output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ .format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */ - .pFilePolicy = NULL /* Not using file output, so NULL */ + .pFilePolicy = &filelog /* Not using file output, so NULL */ }; if (rdk_logger_ext_init(&config) != RDK_SUCCESS) { From 093d54c6cc31f5084a94f3a4aa1b904b57b4008b Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:27:17 +0530 Subject: [PATCH 052/108] Update strategies.c --- uploadstblogs/src/strategies.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 70a11054..3c1a10d5 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1012,6 +1012,28 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) return -1; } + // Check system uptime and sleep if needed + // Script lines 818-836: if uptime < 900s, sleep 330s + double uptime_seconds = 0.0; + if (get_system_uptime(&uptime_seconds)) { + if (uptime_seconds < 900.0) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); + } + } + + /* Record monotonic start time for elapsed-time measurement */ + struct timespec workflow_start; + clock_gettime(CLOCK_MONOTONIC, &workflow_start); + { + time_t now_wall = time(NULL); + struct tm *tm_info = localtime(&now_wall); + char wall_ts[32]; + strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Log upload workflow start wall-clock: %s\n", + __FUNCTION__, __LINE__, wall_ts); + } + // Clean up old log backup directories (older than 3 days) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Cleaning old log backup directories (3+ days)\n", __FUNCTION__, __LINE__); int removed_dirs = cleanup_old_log_backups(ctx->log_path, 3); From 3751c5542281711e2d572ef0ae160d2fdb0b83dd Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:31:46 +0530 Subject: [PATCH 053/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index 03890475..1b74b881 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -462,6 +462,16 @@ int uploadstblogs_execute(int argc, char** argv) /* Release lock and exit */ release_lock(); + /* Log elapsed time between upload start and completion */ + { + struct timespec workflow_end; + clock_gettime(CLOCK_MONOTONIC, &workflow_end); + long elapsed_sec = (long)(workflow_end.tv_sec - workflow_start.tv_sec); + long elapsed_msec = (workflow_end.tv_nsec - workflow_start.tv_nsec) / 1000000L; + if (elapsed_msec < 0) { elapsed_sec--; elapsed_msec += 1000L; } + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Log upload complete. (elapsed: %lds %ldms)\n", __FUNCTION__, __LINE__, elapsed_sec, elapsed_msec); + } + return ret; } From da5e86ec1c4b80ac21e641c77c0d71f991b3e506 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:37:31 +0530 Subject: [PATCH 054/108] Update strategies.c --- uploadstblogs/src/strategies.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 3c1a10d5..cb7de023 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1177,24 +1177,7 @@ static int reboot_archive(RuntimeContext* ctx, SessionState* session) */ static int reboot_upload(RuntimeContext* ctx, SessionState* session) { - bool should_upload = false; RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting upload phase\n", __FUNCTION__, __LINE__); - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] UploadOnReboot set to %s\n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false"); - - // Non-DCM mode (DCM_FLAG=0): Always upload (script line 999: uploadLogOnReboot true) - if (ctx->dcm_flag == 0) { - should_upload = true; - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Non-DCM mode (dcm_flag=0), will always upload logs\n", - __FUNCTION__, __LINE__); - } - else - { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] uploadLog:%s \n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false"); - if ( ctx->upload_on_reboot==1 ) { - should_upload = true; - } - } // Construct full archive path using session archive filename char archive_path[MAX_PATH_LENGTH]; @@ -1206,16 +1189,6 @@ static int reboot_upload(RuntimeContext* ctx, SessionState* session) return -1; } - if (!should_upload) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Upload not allowed based on reboot reason and RFC settings\n", - __FUNCTION__, __LINE__); - strncpy(session->archive_file, archive_path, sizeof(session->archive_file) - 1); - session->archive_file[sizeof(session->archive_file) - 1] = '\0'; - emit_upload_aborted(); - return 0; - } - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Uploading main logs: %s\n", __FUNCTION__, __LINE__, archive_path); @@ -1253,9 +1226,6 @@ static int reboot_upload(RuntimeContext* ctx, SessionState* session) int dri_ret = create_dri_archive(ctx, dri_archive); if (dri_ret == 0) { -#ifndef L2_TEST_ENABLED - sleep(60); -#endif // Upload DRI logs using separate session state SessionState dri_session = *session; // Copy current session config From fc5c650329caa3918d610d5bf692d11fa6a1f9d9 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:55:39 +0530 Subject: [PATCH 055/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index 1b74b881..17c4ef3c 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -232,6 +232,25 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) SessionState session = {0}; int ret = 1; + if (get_system_uptime(&uptime_seconds)) { + if (uptime_seconds < 900.0) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); + } + } + + /* Record monotonic start time for elapsed-time measurement */ + struct timespec workflow_start; + clock_gettime(CLOCK_MONOTONIC, &workflow_start); + { + time_t now_wall = time(NULL); + struct tm *tm_info = localtime(&now_wall); + char wall_ts[32]; + strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Log upload workflow start wall-clock: %s\n", + __FUNCTION__, __LINE__, wall_ts); + } + if (!params) { fprintf(stderr, "Invalid parameters\n"); return 1; @@ -337,6 +356,16 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) /* Release lock and exit */ release_lock(); + + /* Log elapsed time between upload start and completion */ + { + struct timespec workflow_end; + clock_gettime(CLOCK_MONOTONIC, &workflow_end); + long elapsed_sec = (long)(workflow_end.tv_sec - workflow_start.tv_sec); + long elapsed_msec = (workflow_end.tv_nsec - workflow_start.tv_nsec) / 1000000L; + if (elapsed_msec < 0) { elapsed_sec--; elapsed_msec += 1000L; } + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Log upload complete. (elapsed: %lds %ldms)\n", __FUNCTION__, __LINE__, elapsed_sec, elapsed_msec); + } return ret; } @@ -349,6 +378,25 @@ int uploadstblogs_execute(int argc, char** argv) /* Clear context to ensure clean state */ memset(&ctx, 0, sizeof(ctx)); + if (get_system_uptime(&uptime_seconds)) { + if (uptime_seconds < 900.0) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); + } + } + + /* Record monotonic start time for elapsed-time measurement */ + struct timespec workflow_start; + clock_gettime(CLOCK_MONOTONIC, &workflow_start); + { + time_t now_wall = time(NULL); + struct tm *tm_info = localtime(&now_wall); + char wall_ts[32]; + strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Log upload workflow start wall-clock: %s\n", + __FUNCTION__, __LINE__, wall_ts); + } + /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); From b4407d5d4c9605be60293b812f44396117aec5ab Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:56:32 +0530 Subject: [PATCH 056/108] Update strategies.c --- uploadstblogs/src/strategies.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index cb7de023..739f9fcc 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1011,28 +1011,6 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) emit_no_logs_reboot(ctx); return -1; } - - // Check system uptime and sleep if needed - // Script lines 818-836: if uptime < 900s, sleep 330s - double uptime_seconds = 0.0; - if (get_system_uptime(&uptime_seconds)) { - if (uptime_seconds < 900.0) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); - } - } - - /* Record monotonic start time for elapsed-time measurement */ - struct timespec workflow_start; - clock_gettime(CLOCK_MONOTONIC, &workflow_start); - { - time_t now_wall = time(NULL); - struct tm *tm_info = localtime(&now_wall); - char wall_ts[32]; - strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Log upload workflow start wall-clock: %s\n", - __FUNCTION__, __LINE__, wall_ts); - } // Clean up old log backup directories (older than 3 days) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Cleaning old log backup directories (3+ days)\n", __FUNCTION__, __LINE__); From 5f35d10c53e6a190b4bf3786f5251c6f46485efc Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:57:18 +0530 Subject: [PATCH 057/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index 17c4ef3c..c8b817e3 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -50,6 +50,7 @@ #include "system_utils.h" #include "rdk_debug.h" #include "uploadlogsnow.h" +#include "common_device_api.h" #ifdef T2_EVENT_ENABLED #include From 19ef59c466cfd127effde3af36addc1bf49e8cb9 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 23 Jun 2026 00:04:09 +0530 Subject: [PATCH 058/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index c8b817e3..e3b193dd 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -233,7 +233,8 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) SessionState session = {0}; int ret = 1; - if (get_system_uptime(&uptime_seconds)) { + double uptime_seconds = 0.0; + if (get_system_uptime(&uptime_seconds)) { if (uptime_seconds < 900.0) { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); } @@ -379,6 +380,7 @@ int uploadstblogs_execute(int argc, char** argv) /* Clear context to ensure clean state */ memset(&ctx, 0, sizeof(ctx)); + double uptime_seconds = 0.0; if (get_system_uptime(&uptime_seconds)) { if (uptime_seconds < 900.0) { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); From 259b488a4b4c5ec175b849c09b11c104e20a0259 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 23 Jun 2026 05:03:17 +0530 Subject: [PATCH 059/108] Update print statement from 'Hello' to 'Goodbye' --- uploadstblogs/src/context_manager.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/uploadstblogs/src/context_manager.c b/uploadstblogs/src/context_manager.c index 6dae5614..e73b104d 100755 --- a/uploadstblogs/src/context_manager.c +++ b/uploadstblogs/src/context_manager.c @@ -157,20 +157,23 @@ bool init_context(RuntimeContext* ctx) // Initialize RDK Logger /* Extended initialization with programmatic configuration */ //RDK Logger Initialisation + /* rdk_LogOutput_File filelog; strncpy(filelog.fileName, "dcmscript.log", sizeof(filelog.fileName)-1); filelog.fileName[sizeof(filelog.fileName) - 1] = '\0'; strncpy(filelog.fileLocation, "/opt/logs/", sizeof(filelog.fileLocation)-1); filelog.fileLocation[sizeof(filelog.fileLocation) - 1] = '\0'; filelog.fileSizeMax = 10240; - filelog.fileCountMax = 1; + filelog.fileCountMax = 1; */ rdk_logger_ext_config_t config = { .pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */ .loglevel = RDK_LOG_INFO, /* Default log level */ - .output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ + //.output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ + .output = RDKLOG_OUTPUT_CONSOLE .format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */ - .pFilePolicy = &filelog /* Not using file output, so NULL */ + //.pFilePolicy = &filelog /* Not using file output, so NULL */ + .pFilePolicy = NULL }; if (rdk_logger_ext_init(&config) != RDK_SUCCESS) { From b9bda882154e3ca0f45eae4cdf1bca471a17226e Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 23 Jun 2026 05:28:14 +0530 Subject: [PATCH 060/108] Update context_manager.c --- uploadstblogs/src/context_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uploadstblogs/src/context_manager.c b/uploadstblogs/src/context_manager.c index e73b104d..4cadcb63 100755 --- a/uploadstblogs/src/context_manager.c +++ b/uploadstblogs/src/context_manager.c @@ -170,7 +170,7 @@ bool init_context(RuntimeContext* ctx) .pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */ .loglevel = RDK_LOG_INFO, /* Default log level */ //.output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ - .output = RDKLOG_OUTPUT_CONSOLE + .output = RDKLOG_OUTPUT_CONSOLE, .format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */ //.pFilePolicy = &filelog /* Not using file output, so NULL */ .pFilePolicy = NULL From 37d5d12a9140a9dcf445e0ef98aa23166730eaeb Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:39:12 +0530 Subject: [PATCH 061/108] Update strategies.c --- uploadstblogs/src/strategies.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 739f9fcc..5c7586fb 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1140,6 +1140,9 @@ static int reboot_archive(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Archive phase complete\n", __FUNCTION__, __LINE__); +#ifndef L2_TEST_ENABLED + sleep(120); +#endif return 0; } From bebee3f12622aa301366c7c966faedbc18b5d9db Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 23 Jun 2026 23:19:25 +0530 Subject: [PATCH 062/108] Create logupload.service --- logupload.service | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 logupload.service diff --git a/logupload.service b/logupload.service new file mode 100644 index 00000000..6cb5599e --- /dev/null +++ b/logupload.service @@ -0,0 +1,32 @@ +########################################################################## +# If not stated otherwise in this file or this component's LICENSE +# file the following copyright and licenses apply: +# +# Copyright 2024 Comcast Cable Communications Management, LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +########################################################################## + +[Unit] +Description=To start Logupload +After= rbus.service iarmbusd.service network-online.target tr69hostif.service + +[Service] +Type=simple +RemainAfterExit=No +ExecStart=/usr/bin/logupload + +[Install] +WantedBy=multi-user.target From 05f12af369943533cd1602f1488e206c39e096bf Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 24 Jun 2026 07:51:50 +0530 Subject: [PATCH 063/108] Update strategies.c --- uploadstblogs/src/strategies.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 5c7586fb..5e5088fe 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1140,10 +1140,6 @@ static int reboot_archive(RuntimeContext* ctx, SessionState* session) RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Archive phase complete\n", __FUNCTION__, __LINE__); -#ifndef L2_TEST_ENABLED - sleep(120); -#endif - return 0; } From 8b041b8a3b420499095b968134b5c7e9e7741982 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Wed, 24 Jun 2026 08:18:45 +0530 Subject: [PATCH 064/108] Update context_manager.c --- uploadstblogs/src/context_manager.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/uploadstblogs/src/context_manager.c b/uploadstblogs/src/context_manager.c index 4cadcb63..d9c80e76 100755 --- a/uploadstblogs/src/context_manager.c +++ b/uploadstblogs/src/context_manager.c @@ -157,23 +157,23 @@ bool init_context(RuntimeContext* ctx) // Initialize RDK Logger /* Extended initialization with programmatic configuration */ //RDK Logger Initialisation - /* + rdk_LogOutput_File filelog; - strncpy(filelog.fileName, "dcmscript.log", sizeof(filelog.fileName)-1); + strncpy(filelog.fileName, "logupload.log", sizeof(filelog.fileName)-1); filelog.fileName[sizeof(filelog.fileName) - 1] = '\0'; strncpy(filelog.fileLocation, "/opt/logs/", sizeof(filelog.fileLocation)-1); filelog.fileLocation[sizeof(filelog.fileLocation) - 1] = '\0'; filelog.fileSizeMax = 10240; - filelog.fileCountMax = 1; */ + filelog.fileCountMax = 1; rdk_logger_ext_config_t config = { .pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */ .loglevel = RDK_LOG_INFO, /* Default log level */ - //.output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ - .output = RDKLOG_OUTPUT_CONSOLE, + .output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ + //.output = RDKLOG_OUTPUT_CONSOLE, .format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */ - //.pFilePolicy = &filelog /* Not using file output, so NULL */ - .pFilePolicy = NULL + .pFilePolicy = &filelog /* Not using file output, so NULL */ + //.pFilePolicy = NULL }; if (rdk_logger_ext_init(&config) != RDK_SUCCESS) { From 54d187361dd4c37669ffecd1cf3c4e207289e7b0 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:30:27 +0530 Subject: [PATCH 065/108] Update dcm.c --- dcm.c | 85 +++-------------------------------------------------------- 1 file changed, 4 insertions(+), 81 deletions(-) diff --git a/dcm.c b/dcm.c index b999154e..6d7d7375 100755 --- a/dcm.c +++ b/dcm.c @@ -37,7 +37,6 @@ #include "dcm_rbus.h" #include "dcm_cronparse.h" #include "dcm_schedjob.h" -#include "uploadstblogs.h" static DCMDHandle *g_pdcmHandle = NULL; @@ -69,73 +68,7 @@ static VOID dcmRunJobs(const INT8* profileName, VOID *pHandle) pRDKPath = DCM_LIB_PATH; } - if(strcmp(profileName, DCM_LOGUPLOAD_SCHED) == 0) { - INT8 *pPrctl = dcmSettingsGetUploadProtocol(pdcmHandle->pDcmSetHandle); - INT8 *pURL = dcmSettingsGetUploadURL(pdcmHandle->pDcmSetHandle); - - if(pPrctl == NULL) { - DCMWarn("Log Upload protocol is NULL, using HTTP\n"); - pPrctl = "HTTP"; - } - if(pURL == NULL) { - DCMWarn("Log Upload URL is NULL, using %s\n", DCM_DEF_LOG_URL); - pURL = DCM_DEF_LOG_URL; - } - - DCMInfo("\nStart log upload via library API\n"); - - /* Log wall-clock time and elapsed time since DCM start */ - { - struct timespec now_ts; - clock_gettime(CLOCK_MONOTONIC, &now_ts); - long elapsed_sec = (long)(now_ts.tv_sec - pdcmHandle->start_time.tv_sec); - long elapsed_msec = (now_ts.tv_nsec - pdcmHandle->start_time.tv_nsec) / 1000000L; - if (elapsed_msec < 0) { elapsed_sec--; elapsed_msec += 1000L; } - - time_t wall = time(NULL); - struct tm *tm_info = localtime(&wall); - char wall_ts[32]; - strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); - DCMInfo("Log upload start wall-clock time: %s (elapsed since DCM start: %lds %ldms)\n", - wall_ts, elapsed_sec, elapsed_msec); - } - - // Call uploadstblogs library API instead of shell script - UploadSTBLogsParams params = { - .flag = 0, - .dcm_flag = 1, - .upload_on_reboot = false, - .upload_protocol = pPrctl, - .upload_http_link = pURL, - .trigger_type = TRIGGER_SCHEDULED, - .rrd_flag = false, - .rrd_file = NULL - }; -#ifndef GTEST_ENABLE - int result = uploadstblogs_run(¶ms); - { - struct timespec done_ts; - clock_gettime(CLOCK_MONOTONIC, &done_ts); - long upload_sec = (long)(done_ts.tv_sec - pdcmHandle->start_time.tv_sec); - long upload_msec = (done_ts.tv_nsec - pdcmHandle->start_time.tv_nsec) / 1000000L; - if (upload_msec < 0) { upload_sec--; upload_msec += 1000L; } - if (result != 0) { - DCMError("Log upload failed with error code: %d (elapsed since DCM start: %lds %ldms)\n", - result, upload_sec, upload_msec); - } else { - DCMInfo("Log upload completed successfully (elapsed since DCM start: %lds %ldms)\n", - upload_sec, upload_msec); - } - } - - if (result != 0) { - DCMError("Log upload failed with error code: %d\n", result); - } else { - DCMInfo("Log upload completed successfully\n"); - } -#endif - } - else if(strcmp(profileName, DCM_DIFD_SCHED) == 0) { + if(strcmp(profileName, DCM_DIFD_SCHED) == 0) { DCMInfo("Start FW update Script\n"); snprintf(pExecBuff, EXECMD_BUFF_SIZE, "/bin/sh %s/swupdate_utility.sh 0 2 >> /opt/logs/swupdate.log 2>&1", pRDKPath); @@ -233,15 +166,6 @@ INT32 dcmDaemonMainInit(DCMDHandle *pdcmHandle) return ret; } - /* Add log upload job to Schecduler */ - pdcmHandle->pLogSchedHandle = dcmSchedAddJob(DCM_LOGUPLOAD_SCHED, - (DCMSchedCB)dcmRunJobs, - (VOID *) pdcmHandle); - if(pdcmHandle->pLogSchedHandle == NULL) { - DCMError("Failed to Add Log Scheduler jobs\n"); - return DCM_FAILURE; - } - /* Add FW update job to Schecduler */ pdcmHandle->pDifdSchedHandle = dcmSchedAddJob(DCM_DIFD_SCHED, (DCMSchedCB)dcmRunJobs, @@ -272,9 +196,7 @@ VOID dcmDaemonMainUnInit(DCMDHandle *pdcmHandle) dcmSettingsUnInit(pdcmHandle->pDcmSetHandle); dcmRbusUnInit(pdcmHandle->pRbusHandle); - dcmSchedStopJob(pdcmHandle->pLogSchedHandle); dcmSchedStopJob(pdcmHandle->pDifdSchedHandle); - dcmSchedRemoveJob(pdcmHandle->pLogSchedHandle); dcmSchedRemoveJob(pdcmHandle->pDifdSchedHandle); dcmSchedUnInit(); @@ -310,6 +232,7 @@ int main(int argc, char* argv[]) g_pdcmHandle->isDebugEnabled = true; DCMInfo("Starting DCM Process: %d\n", getpid()); + /* Record monotonic start time for elapsed-time measurements */ clock_gettime(CLOCK_MONOTONIC, &g_pdcmHandle->start_time); { @@ -408,11 +331,11 @@ int main(int argc, char* argv[]) continue; } + INT8 unusedLogCron[16] = {0}; ret = dcmSettingParseConf(g_pdcmHandle->pDcmSetHandle, pconfPath, - g_pdcmHandle->logCron, + unusedLogCron, g_pdcmHandle->difdCron); if(ret == DCM_SUCCESS) { - dcmSchedStartJob(g_pdcmHandle->pLogSchedHandle, g_pdcmHandle->logCron); dcmSchedStartJob(g_pdcmHandle->pDifdSchedHandle, g_pdcmHandle->difdCron); ret = dcmIARMEvntSend(DCM_IARM_COMPLETE); From da952f5e04b1a2d18a70b5eab5f78f81679d22f7 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:43:09 +0530 Subject: [PATCH 066/108] Update dcm.h --- dcm.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dcm.h b/dcm.h index f47cca59..62fea410 100644 --- a/dcm.h +++ b/dcm.h @@ -26,7 +26,8 @@ extern "C" { #endif -#define DCM_LOGUPLOAD_SCHED "DCM_LOG_UPLOAD" +#include + #define DCM_DIFD_SCHED "DCM_FW_UPDATE" typedef struct _dcmdHandle @@ -35,10 +36,8 @@ typedef struct _dcmdHandle BOOL isDCMRunning; VOID *pRbusHandle; VOID *pDcmSetHandle; - VOID *pLogSchedHandle; VOID *pDifdSchedHandle; INT8 *pExecBuff; - INT8 logCron[16]; INT8 difdCron[16]; struct timespec start_time; /* Monotonic timestamp at DCM process start */ From 5f08129f6d44e0d38106ebae959544a52afe4ed8 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:43:44 +0530 Subject: [PATCH 067/108] Update fmt.Println message from 'Hello' to 'Goodbye' --- dcm_parseconf.c | 67 ------------------------------------------------- 1 file changed, 67 deletions(-) diff --git a/dcm_parseconf.c b/dcm_parseconf.c index a2adbd5b..7f92e75e 100755 --- a/dcm_parseconf.c +++ b/dcm_parseconf.c @@ -37,7 +37,6 @@ #include "dcm_utils.h" #include "dcm_rbus.h" #include "dcm_parseconf.h" -#include "uploadstblogs.h" static INT32 g_bMMEnable = 0; @@ -578,72 +577,6 @@ INT32 dcmSettingParseConf(VOID *pHandle, INT8 *pConffile, DCMInfo("DCM_DIFD_CRON: %s\n", pDifdCron); - if(uploadCheck == 1 && pdcmSetHandle->bRebootFlag == 0) { - DCMInfo("Triggering log upload with reboot flag via library API\n"); - UploadSTBLogsParams params = { - .flag = 1, - .dcm_flag = 1, - .upload_on_reboot = true, - .upload_protocol = pUploadprtl, - .upload_http_link = pUploadURL, - .trigger_type = TRIGGER_REBOOT, - .rrd_flag = false, - .rrd_file = NULL - }; -#ifndef GTEST_ENABLE - int result = uploadstblogs_run(¶ms); - if (result != 0) { - DCMError("Log upload (reboot=true) failed: %d\n", result); - } -#endif - } - else if (uploadCheck == 0 && pdcmSetHandle->bRebootFlag == 0) { - DCMInfo("Triggering log upload without reboot flag via library API\n"); - UploadSTBLogsParams params = { - .flag = 1, - .dcm_flag = 1, - .upload_on_reboot = false, - .upload_protocol = pUploadprtl, - .upload_http_link = pUploadURL, - .trigger_type = TRIGGER_SCHEDULED, - .rrd_flag = false, - .rrd_file = NULL - }; -#ifndef GTEST_ENABLE - int result = uploadstblogs_run(¶ms); - if (result != 0) { - DCMError("Log upload (reboot=false) failed: %d\n", result); - } -#endif - } - else { - DCMWarn ("Nothing to do here for uploadCheck value = %d\n", uploadCheck); - } - - if(strlen(pLogCron) == 0) { - DCMWarn ("Uploading logs as DCM response is either null or not present\n"); - - UploadSTBLogsParams params = { - .flag = 1, - .dcm_flag = 1, - .upload_on_reboot = false, - .upload_protocol = pUploadprtl, - .upload_http_link = pUploadURL, - .trigger_type = TRIGGER_SCHEDULED, - .rrd_flag = false, - .rrd_file = NULL - }; -#ifndef GTEST_ENABLE - int result = uploadstblogs_run(¶ms); - if (result != 0) { - DCMError("Log upload (empty cron) failed: %d\n", result); - } -#endif - } - else { - DCMInfo ("%s is present setting cron jobs\n", DCM_LOGUPLOAD_CRON); - } - if(strlen(pDifdCron) == 0) { DCMWarn ("difdCron is empty\n"); } From 832e3954325bfcc13b6eba67209dd622a6fd5d14 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:45:39 +0530 Subject: [PATCH 068/108] Update event_manager.c --- uploadstblogs/src/event_manager.c | 127 +++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/src/event_manager.c b/uploadstblogs/src/event_manager.c index 00f50980..ff9c3cb9 100755 --- a/uploadstblogs/src/event_manager.c +++ b/uploadstblogs/src/event_manager.c @@ -36,7 +36,9 @@ #if defined(IARM_ENABLED) #include "libIBus.h" #include "sysMgr.h" - +#ifdef EN_MAINTENANCE_MANAGER +#include "maintenanceMGR.h" +#endif static bool iarm_initialized = false; #define IARM_UPLOADSTB_EVENT "UploadSTBLogsEvent" @@ -51,12 +53,37 @@ static bool iarm_initialized = false; #define LOG_UPLOAD_FAILED 1 #define LOG_UPLOAD_ABORTED 2 +#define MAINT_LOGUPLOAD_COMPLETE 4 +#define MAINT_LOGUPLOAD_ERROR 5 +#define MAINT_LOGUPLOAD_INPROGRESS 16 + +// Check maintenance mode (matches script ENABLE_MAINTENANCE check) +static bool is_maintenance_enabled(void) +{ + char buffer[32] = {0}; + if (getDevicePropertyData("ENABLE_MAINTENANCE", buffer, sizeof(buffer)) == UTILS_SUCCESS) { + return (strcasecmp(buffer, "true") == 0); + } + return false; +} + +// Check device type (matches script DEVICE_TYPE check) +static bool is_device_broadband(const RuntimeContext* ctx) +{ + if (!ctx) { + return false; + } + return (strcmp(ctx->device_type, "broadband") == 0); +} void emit_privacy_abort(void) { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Upload aborted due to privacy mode\n", __FUNCTION__, __LINE__); + // Send maintenance complete event (matches script behavior) + // Script sends MAINT_LOGUPLOAD_COMPLETE=4 for privacy mode, not ERROR + send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); } void emit_no_logs_reboot(const RuntimeContext* ctx) @@ -71,12 +98,23 @@ void emit_no_logs_reboot(const RuntimeContext* ctx) return; } + // Send maintenance complete event only if device is not broadband and maintenance enabled + // Matches script uploadLogOnReboot line 810: if [ "$DEVICE_TYPE" != "broadband" ] && [ "x$ENABLE_MAINTENANCE" == "xtrue" ] + if (!is_device_broadband(ctx) && is_maintenance_enabled() && ctx->rrd_flag == 0) { + send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); + } } void emit_no_logs_ondemand(void) { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Log directory empty, skipping log upload\n", __FUNCTION__, __LINE__); + + // Send maintenance complete event only if maintenance enabled (no device type check) + // Matches script uploadLogOnDemand line 746: if [ "x$ENABLE_MAINTENANCE" == "xtrue" ] + if (is_maintenance_enabled()) { + send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); + } } void emit_upload_success(const RuntimeContext* ctx, const SessionState* session) @@ -105,6 +143,11 @@ void emit_upload_success(const RuntimeContext* ctx, const SessionState* session) // Send success events (matches script behavior) send_iarm_event("LogUploadEvent", LOG_UPLOAD_SUCCESS); + + // Send maintenance event only if device is not broadband and maintenance enabled + if (ctx && !is_device_broadband(ctx) && is_maintenance_enabled() && ctx->rrd_flag == 0) { + send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); + } } void emit_upload_failure(const RuntimeContext* ctx, const SessionState* session) @@ -132,6 +175,10 @@ void emit_upload_failure(const RuntimeContext* ctx, const SessionState* session) // Send failure events (matches script behavior) send_iarm_event("LogUploadEvent", LOG_UPLOAD_FAILED); + // Send maintenance event only if device is not broadband and maintenance enabled + if (!is_device_broadband(ctx) && is_maintenance_enabled()) { + send_iarm_event_maintenance(MAINT_LOGUPLOAD_ERROR); + } } void emit_upload_aborted(void) @@ -140,6 +187,30 @@ void emit_upload_aborted(void) "[%s:%d] Not Uploading Logs with DCM \n", __FUNCTION__, __LINE__); send_iarm_event("LogUploadEvent", LOG_UPLOAD_FAILED); + send_iarm_event_maintenance(MAINT_LOGUPLOAD_ERROR); +} + +void emit_fallback(UploadPath from_path, UploadPath to_path) +{ + const char* from_str = (from_path == PATH_DIRECT) ? "Direct" : "CodeBig"; + const char* to_str = (to_path == PATH_DIRECT) ? "Direct" : "CodeBig"; + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Upload fallback: switching from %s to %s path\n", + __FUNCTION__, __LINE__, from_str, to_str); + + // Note: Script doesn't send specific fallback events, just logs the switch +} + +void emit_upload_start(void) +{ + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Starting upload operation\n", __FUNCTION__, __LINE__); + + // Note: MAINT_LOGUPLOAD_INPROGRESS is sent in different contexts: + // 1. When lock acquisition fails (handled in main()) + // 2. During normal upload start (here) - but script doesn't send this here + // Script only sends MAINT_LOGUPLOAD_INPROGRESS on lock failure, not normal start } #ifndef GTEST_ENABLE @@ -273,6 +344,50 @@ void send_iarm_event(const char* event_name, int event_code) } } +/** + * @brief Send maintenance manager IARM event + * Based on rdkfwupdater iarmInterface.c eventManager() MaintenanceMGR section + */ +void send_iarm_event_maintenance(int maint_event_code) +{ +#ifdef EN_MAINTENANCE_MANAGER + if (!init_iarm_connection()) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] IARM not initialized, skipping maintenance event\n", __FUNCTION__, __LINE__); + return; + } + + IARM_Bus_MaintMGR_EventData_t infoStatus; + IARM_Result_t ret_code; + + memset(&infoStatus, 0, sizeof(IARM_Bus_MaintMGR_EventData_t)); + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Sending MaintenanceMGR event with code: %d\n", + __FUNCTION__, __LINE__, maint_event_code); + + infoStatus.data.maintenance_module_status.status = (IARM_Maint_module_status_t)maint_event_code; + + ret_code = IARM_Bus_BroadcastEvent(IARM_BUS_MAINTENANCE_MGR_NAME, + (IARM_EventId_t)IARM_BUS_MAINTENANCEMGR_EVENT_UPDATE, + (void*)&infoStatus, sizeof(infoStatus)); + + if (ret_code == IARM_RESULT_SUCCESS) { + RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, + "[%s:%d] MaintenanceMGR event sent successfully: %d\n", + __FUNCTION__, __LINE__, maint_event_code); + } else { + RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, + "[%s:%d] MaintenanceMGR event failed: %d (result: %d)\n", + __FUNCTION__, __LINE__, maint_event_code, ret_code); + } +#else + RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, + "[%s:%d] Maintenance Manager not enabled, skipping event: %d\n", + __FUNCTION__, __LINE__, maint_event_code); +#endif +} + /** * @brief Cleanup IARM connection * Based on rdkfwupdater iarmrInterface.c term_event_handler() @@ -297,6 +412,13 @@ void send_iarm_event(const char* event_name, int event_code) __FUNCTION__, __LINE__, event_name ? event_name : "NULL", event_code); } +void send_iarm_event_maintenance(int maint_event_code) +{ + RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, + "[%s:%d] IARM disabled - would send maintenance event: %d\n", + __FUNCTION__, __LINE__, maint_event_code); +} + void cleanup_iarm_connection(void) { // No-op when IARM disabled @@ -308,5 +430,8 @@ void emit_folder_missing_error(void) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] Required folder missing for log upload\n", __FUNCTION__, __LINE__); + + // Send maintenance complete event (matches script behavior) + send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE); } From 220f696eda3cc19aace8938417fb7dc1e78b0bc2 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:48:00 +0530 Subject: [PATCH 069/108] Update dcm.c --- dcm.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/dcm.c b/dcm.c index 6d7d7375..a5f5574f 100755 --- a/dcm.c +++ b/dcm.c @@ -233,16 +233,6 @@ int main(int argc, char* argv[]) DCMInfo("Starting DCM Process: %d\n", getpid()); - /* Record monotonic start time for elapsed-time measurements */ - clock_gettime(CLOCK_MONOTONIC, &g_pdcmHandle->start_time); - { - time_t now = time(NULL); - struct tm *tm_info = localtime(&now); - char wall_ts[32]; - strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); - DCMInfo("DCM start wall-clock time: %s\n", wall_ts); - } - /* Create child process */ process_id = fork(); if (process_id < 0) { From bc52e779ae01c1c9c893bf0be7d16b9efe5e2aad Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:49:34 +0530 Subject: [PATCH 070/108] Update dcm.h --- dcm.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/dcm.h b/dcm.h index 62fea410..3d157849 100644 --- a/dcm.h +++ b/dcm.h @@ -26,7 +26,6 @@ extern "C" { #endif -#include #define DCM_DIFD_SCHED "DCM_FW_UPDATE" @@ -39,7 +38,6 @@ typedef struct _dcmdHandle VOID *pDifdSchedHandle; INT8 *pExecBuff; INT8 difdCron[16]; - struct timespec start_time; /* Monotonic timestamp at DCM process start */ } DCMDHandle; From 29ed97514d6c8eb10963bc188a9ab95b116a59e1 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:51:25 +0530 Subject: [PATCH 071/108] Update event_manager.h --- uploadstblogs/include/event_manager.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/uploadstblogs/include/event_manager.h b/uploadstblogs/include/event_manager.h index ee342503..716b3c8b 100755 --- a/uploadstblogs/include/event_manager.h +++ b/uploadstblogs/include/event_manager.h @@ -67,6 +67,11 @@ void emit_upload_failure(const RuntimeContext* ctx, const SessionState* session) */ void emit_upload_aborted(void); +/** + * @brief Emit upload start event + */ +void emit_upload_start(void); + /** * @brief Emit fallback event * @param from_path Original path @@ -81,6 +86,11 @@ void emit_fallback(UploadPath from_path, UploadPath to_path); */ void send_iarm_event(const char* event_name, int event_code); +/** + * @brief Send maintenance manager IARM event + * @param maint_event_code Maintenance event code + */ +void send_iarm_event_maintenance(int maint_event_code); /** * @brief Cleanup IARM connection resources From 5fcbbfa6ed188d128f2d67bedbb3c40e5b295ef1 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:54:50 +0530 Subject: [PATCH 072/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 76 ++++++------------------------- 1 file changed, 15 insertions(+), 61 deletions(-) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index e3b193dd..89828dc7 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -50,7 +50,6 @@ #include "system_utils.h" #include "rdk_debug.h" #include "uploadlogsnow.h" -#include "common_device_api.h" #ifdef T2_EVENT_ENABLED #include @@ -233,26 +232,6 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) SessionState session = {0}; int ret = 1; - double uptime_seconds = 0.0; - if (get_system_uptime(&uptime_seconds)) { - if (uptime_seconds < 900.0) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); - } - } - - /* Record monotonic start time for elapsed-time measurement */ - struct timespec workflow_start; - clock_gettime(CLOCK_MONOTONIC, &workflow_start); - { - time_t now_wall = time(NULL); - struct tm *tm_info = localtime(&now_wall); - char wall_ts[32]; - strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Log upload workflow start wall-clock: %s\n", - __FUNCTION__, __LINE__, wall_ts); - } - if (!params) { fprintf(stderr, "Invalid parameters\n"); return 1; @@ -264,6 +243,9 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); + if (is_maintenance_enabled()) { + send_iarm_event_maintenance(16); + } return 1; } @@ -318,6 +300,9 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) return 0; } + /* Emit upload start event */ + emit_upload_start(); + /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { if (!file_exists(ctx.rrd_file)) { @@ -358,16 +343,6 @@ int uploadstblogs_run(const UploadSTBLogsParams* params) /* Release lock and exit */ release_lock(); - - /* Log elapsed time between upload start and completion */ - { - struct timespec workflow_end; - clock_gettime(CLOCK_MONOTONIC, &workflow_end); - long elapsed_sec = (long)(workflow_end.tv_sec - workflow_start.tv_sec); - long elapsed_msec = (workflow_end.tv_nsec - workflow_start.tv_nsec) / 1000000L; - if (elapsed_msec < 0) { elapsed_sec--; elapsed_msec += 1000L; } - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Log upload complete. (elapsed: %lds %ldms)\n", __FUNCTION__, __LINE__, elapsed_sec, elapsed_msec); - } return ret; } @@ -380,29 +355,13 @@ int uploadstblogs_execute(int argc, char** argv) /* Clear context to ensure clean state */ memset(&ctx, 0, sizeof(ctx)); - double uptime_seconds = 0.0; - if (get_system_uptime(&uptime_seconds)) { - if (uptime_seconds < 900.0) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] System uptime %.0f seconds \n", __FUNCTION__, __LINE__, uptime_seconds); - } - } - - /* Record monotonic start time for elapsed-time measurement */ - struct timespec workflow_start; - clock_gettime(CLOCK_MONOTONIC, &workflow_start); - { - time_t now_wall = time(NULL); - struct tm *tm_info = localtime(&now_wall); - char wall_ts[32]; - strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Log upload workflow start wall-clock: %s\n", - __FUNCTION__, __LINE__, wall_ts); - } - /* Acquire lock to ensure single instance */ if (!acquire_lock("/tmp/.log-upload.lock")) { fprintf(stderr, "Failed to acquire lock - another instance running\n"); + /* Script sends MAINT_LOGUPLOAD_INPROGRESS when another instance is already running */ + if (is_maintenance_enabled()) { + send_iarm_event_maintenance(16); // Matches script: eventSender "MaintenanceMGR" $MAINT_LOGUPLOAD_INPROGRESS + } return 1; } @@ -469,6 +428,11 @@ int uploadstblogs_execute(int argc, char** argv) return 0; } + /* Note: STRAT_NO_LOGS removed - each strategy now checks for logs internally */ + + /* Emit upload start event (matches script MAINT_LOGUPLOAD_INPROGRESS) */ + emit_upload_start(); + /* Prepare archive based on strategy */ if (strategy == STRAT_RRD) { // RRD: Upload pre-existing archive file directly (provided via command line) @@ -513,16 +477,6 @@ int uploadstblogs_execute(int argc, char** argv) /* Release lock and exit */ release_lock(); - /* Log elapsed time between upload start and completion */ - { - struct timespec workflow_end; - clock_gettime(CLOCK_MONOTONIC, &workflow_end); - long elapsed_sec = (long)(workflow_end.tv_sec - workflow_start.tv_sec); - long elapsed_msec = (workflow_end.tv_nsec - workflow_start.tv_nsec) / 1000000L; - if (elapsed_msec < 0) { elapsed_sec--; elapsed_msec += 1000L; } - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Log upload complete. (elapsed: %lds %ldms)\n", __FUNCTION__, __LINE__, elapsed_sec, elapsed_msec); - } - return ret; } From 856fd781fa5c847c259bc242671757c655c36531 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:56:14 +0530 Subject: [PATCH 073/108] Update uploadstblogs.c --- uploadstblogs/src/uploadstblogs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/uploadstblogs/src/uploadstblogs.c b/uploadstblogs/src/uploadstblogs.c index 89828dc7..7f29b2eb 100755 --- a/uploadstblogs/src/uploadstblogs.c +++ b/uploadstblogs/src/uploadstblogs.c @@ -493,3 +493,4 @@ int main(int argc, char** argv) } #endif /* UPLOADSTBLOGS_BUILD_BINARY */ + From d0de4f95200cee3b52d09fe952f5ebac902ed530 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 11:26:38 +0530 Subject: [PATCH 074/108] Update strategies.c --- uploadstblogs/src/strategies.c | 109 +++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 5e5088fe..e38cbed3 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -249,7 +249,6 @@ static int wait_for_reboot_reason(void) RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling\n", __FUNCTION__, __LINE__, errno); - goto fallback_poll; } int wd = inotify_add_watch(ifd, PATH_FLAG_INVOCATION_DIR, @@ -259,7 +258,6 @@ static int wait_for_reboot_reason(void) "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling\n", __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION_DIR, errno); close(ifd); - goto fallback_poll; } /* Re-check after watch is set — closes race between access() and add_watch */ @@ -277,7 +275,6 @@ static int wait_for_reboot_reason(void) __FUNCTION__, __LINE__, errno); inotify_rm_watch(ifd, wd); close(ifd); - goto fallback_poll; } deadline.tv_sec += (time_t)REBOOT_POLL_TIMEOUT_S; @@ -323,22 +320,108 @@ static int wait_for_reboot_reason(void) close(ifd); return found ? 0 : -1; } +} + + +/** + * wait_for_telemetry_prevlogs_done - Wait for telemetry previous-log grep sentinel. + * + * Uses inotify to watch TELEMETRY_PREVLOGS_DONE_DIR for creation of + * TELEMETRY_PREVLOGS_DONE_FILENAME. A select() loop with a 2-second heartbeat + * drives the wait; the total window is bounded by TELEMETRY_PREVLOGS_TIMEOUT_S + * measured on CLOCK_MONOTONIC. + * + * Falls back to polling if inotify_init1 or inotify_add_watch fails. + * + * Returns 0 when the sentinel is present (telemetry grep complete). + * Returns -1 on timeout. A timeout does NOT abort the upload; the caller + * annotates the session and proceeds. + */ +static int wait_for_telemetry_prevlogs_done(void) +{ + /* Fast path: sentinel already present */ + if (access(TELEMETRY_PREVLOGS_DONE_FLAG, F_OK) == 0) { + return 0; + } + + int ifd = inotify_init1(IN_CLOEXEC); + if (ifd < 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, errno); + } + + int wd = inotify_add_watch(ifd, TELEMETRY_PREVLOGS_DONE_DIR, + IN_CREATE | IN_MOVED_TO); + if (wd < 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, TELEMETRY_PREVLOGS_DONE_DIR, errno); + close(ifd); + } + + /* Re-check after watch is set — closes race between access() and add_watch */ + if (access(TELEMETRY_PREVLOGS_DONE_FLAG, F_OK) == 0) { + inotify_rm_watch(ifd, wd); + close(ifd); + return 0; + } -fallback_poll: { - struct timespec start, now; - clock_gettime(CLOCK_MONOTONIC, &start); - for (;;) { - if (access(PATH_FLAG_INVOCATION, F_OK) == 0) { return 0; } - clock_gettime(CLOCK_MONOTONIC, &now); - if ((now.tv_sec - start.tv_sec) >= (time_t)REBOOT_POLL_TIMEOUT_S) { - return -1; + struct timespec deadline; + if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] clock_gettime failed (errno=%d); falling back to polling\n", + __FUNCTION__, __LINE__, errno); + inotify_rm_watch(ifd, wd); + close(ifd); + } + deadline.tv_sec += (time_t)TELEMETRY_PREVLOGS_TIMEOUT_S; + + int found = 0; + char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; + + while (!found) { + struct timespec now; + if (clock_gettime(CLOCK_MONOTONIC, &now) == 0 && + now.tv_sec >= deadline.tv_sec) { + break; /* timeout */ + } + + struct timeval tv = {2, 0}; + fd_set fds; + FD_ZERO(&fds); + FD_SET(ifd, &fds); + + int ret = select(ifd + 1, &fds, NULL, NULL, &tv); + if (ret < 0) { + if (errno == EINTR) { continue; } + break; + } + if (ret == 0) { continue; } /* heartbeat — re-check deadline */ + + ssize_t len = read(ifd, buf, sizeof(buf)); + if (len <= 0) { continue; } + + ssize_t offset = 0; + while (offset < len) { + struct inotify_event *ev = + (struct inotify_event *)(buf + offset); + if (ev->len > 0 && + strcmp(ev->name, TELEMETRY_PREVLOGS_DONE_FILENAME) == 0) { + found = 1; + break; + } + offset += (ssize_t)(sizeof(struct inotify_event) + ev->len); } - sleep(REBOOT_POLL_INTERVAL_S); } + + inotify_rm_watch(ifd, wd); + close(ifd); + return found ? 0 : -1; } -} +} /** * set_upload_annotation - Record a prerequisite-failure annotation in the session. From 3861a8f9510755780c37fc71706e9d579b8748fb Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 11:42:34 +0530 Subject: [PATCH 075/108] Update strategies.c --- uploadstblogs/src/strategies.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index e38cbed3..dc439dfb 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1080,6 +1080,30 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) } } + /* Wait for telemetry previous-log grep completion sentinel (REQ-SYNC-003). + * Telemetry writes TELEMETRY_PREVLOGS_DONE_FLAG after it finishes grepping + * PreviousLogs. Uploading before this sentinel appears could cause telemetry + * to lose data from the previous boot. This is a soft gate — on timeout the + * upload still proceeds and the session is annotated. */ + { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Waiting for telemetry prevlogs sentinel %s (timeout %us)\n", + __FUNCTION__, __LINE__, TELEMETRY_PREVLOGS_DONE_FLAG, + TELEMETRY_PREVLOGS_TIMEOUT_S); + + if (wait_for_telemetry_prevlogs_done() != 0) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] Telemetry prevlogs sentinel not present after %us; " + "proceeding without telemetry sync\n", + __FUNCTION__, __LINE__, TELEMETRY_PREVLOGS_TIMEOUT_S); + session->upload_annotations |= (1 << ANNOTATION_TELEMETRY_PREVLOGS_UNAVAILABLE); + } else { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Telemetry prevlogs sentinel detected. Proceeding.\n", + __FUNCTION__, __LINE__); + } + } + // Check if PREV_LOG_PATH exists and has .txt or .log files if (!dir_exists(ctx->prev_log_path)) { RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, From 14fb2bf1c128e866b1c7be83cb8d9423bf0e9101 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 11:53:36 +0530 Subject: [PATCH 076/108] Update strategies.c --- uploadstblogs/src/strategies.c | 59 +++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index dc439dfb..e507a764 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1261,7 +1261,64 @@ static int reboot_archive(RuntimeContext* ctx, SessionState* session) */ static int reboot_upload(RuntimeContext* ctx, SessionState* session) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] REBOOT/NON_DCM: Starting upload phase\n", __FUNCTION__, __LINE__); + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] REBOOT/NON_DCM: Starting upload phase\n", __FUNCTION__, __LINE__); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] UploadOnReboot set to %s\n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false"); + + // Check reboot reason and RFC settings (matches script logic) + // Script: if [ "$uploadLog" == "true" ] || [ -z "$reboot_reason" -a "$DISABLE_UPLOAD_LOGS_UNSHEDULED_REBOOT" == "false" ] + // Note: When DCM_FLAG=0 (Non-DCM), script ALWAYS passes "true" regardless of UploadOnReboot value + // When DCM_FLAG=1 (DCM mode), upload_on_reboot determines the behavior + bool should_upload = false; + const char* reboot_info_path = "/opt/secure/reboot/previousreboot.info"; + + // Non-DCM mode (DCM_FLAG=0): Always upload (script line 999: uploadLogOnReboot true) + if (ctx->dcm_flag == 0) { + should_upload = true; + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Non-DCM mode (dcm_flag=0), will always upload logs\n", + __FUNCTION__, __LINE__); + } + else { + // Check reboot reason file for scheduled reboot (grep -i "Scheduled Reboot\|MAINTENANCE_REBOOT") + bool is_scheduled_reboot = false; + FILE* reboot_file = fopen(reboot_info_path, "r"); + if (reboot_file) { + char line[512]; + while (fgets(line, sizeof(line), reboot_file)) { + // Look for "Scheduled Reboot" or "MAINTENANCE_REBOOT" (case insensitive) + if (strcasestr(line, "Scheduled Reboot") || strcasestr(line, "MAINTENANCE_REBOOT")) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] reboot_reason: %s \n", __FUNCTION__, __LINE__,line); + is_scheduled_reboot = true; + break; + } + } + fclose(reboot_file); + } else { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] Could not open reboot reason file: %s\n", __FUNCTION__, __LINE__, reboot_info_path); + } + + // Get RFC setting for unscheduled reboot upload via RBUS + bool disable_unscheduled_upload = false; + if (!rbus_get_bool_param("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.UploadLogsOnUnscheduledReboot.Disable", + &disable_unscheduled_upload)) { + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, + "[%s:%d] Failed to get UploadLogsOnUnscheduledReboot.Disable RFC, assuming false\n", + __FUNCTION__, __LINE__); + disable_unscheduled_upload = false; + } + + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] uploadLog:%s and UploadLogsOnUnscheduledReboot.Disable RFC: %s\n", __FUNCTION__, __LINE__, ctx->upload_on_reboot ? "true" : "false", disable_unscheduled_upload ? "true" : "false"); + + // Upload if upload_on_reboot is enabled, OR if the reboot is unscheduled + // and the UploadLogsOnUnscheduledReboot.Disable RFC does not disable it. + // Script logic for the unscheduled reboot path: + // [ -z "$reboot_reason" -a "$DISABLE_UPLOAD_LOGS_UNSHEDULED_REBOOT" == "false" ] + if ( ctx->upload_on_reboot==1 || (!is_scheduled_reboot && !disable_unscheduled_upload)) { + should_upload = true; + } + } // Construct full archive path using session archive filename char archive_path[MAX_PATH_LENGTH]; From 2728a725053e1b80c4a2c4d8fdd2ce6bf63b55f5 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 11:57:07 +0530 Subject: [PATCH 077/108] Update strategies.c --- uploadstblogs/src/strategies.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index e507a764..eaf68dab 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -1329,7 +1329,16 @@ static int reboot_upload(RuntimeContext* ctx, SessionState* session) "[%s:%d] Archive path too long\n", __FUNCTION__, __LINE__); return -1; } - + + if (!should_upload) { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, + "[%s:%d] Upload not allowed based on reboot reason and RFC settings\n", + __FUNCTION__, __LINE__); + strncpy(session->archive_file, archive_path, sizeof(session->archive_file) - 1); + session->archive_file[sizeof(session->archive_file) - 1] = '\0'; + emit_upload_aborted(); + return 0; + } RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Uploading main logs: %s\n", __FUNCTION__, __LINE__, archive_path); From 977c69b47f0b9bd103d8f728b4cf9a630237abb2 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 12:01:47 +0530 Subject: [PATCH 078/108] Update context_manager.c --- uploadstblogs/src/context_manager.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/uploadstblogs/src/context_manager.c b/uploadstblogs/src/context_manager.c index d9c80e76..a62e3c34 100755 --- a/uploadstblogs/src/context_manager.c +++ b/uploadstblogs/src/context_manager.c @@ -157,23 +157,23 @@ bool init_context(RuntimeContext* ctx) // Initialize RDK Logger /* Extended initialization with programmatic configuration */ //RDK Logger Initialisation - + /* rdk_LogOutput_File filelog; strncpy(filelog.fileName, "logupload.log", sizeof(filelog.fileName)-1); filelog.fileName[sizeof(filelog.fileName) - 1] = '\0'; strncpy(filelog.fileLocation, "/opt/logs/", sizeof(filelog.fileLocation)-1); filelog.fileLocation[sizeof(filelog.fileLocation) - 1] = '\0'; filelog.fileSizeMax = 10240; - filelog.fileCountMax = 1; + filelog.fileCountMax = 1; */ rdk_logger_ext_config_t config = { .pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */ .loglevel = RDK_LOG_INFO, /* Default log level */ - .output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ - //.output = RDKLOG_OUTPUT_CONSOLE, + //.output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ + .output = RDKLOG_OUTPUT_CONSOLE, .format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */ - .pFilePolicy = &filelog /* Not using file output, so NULL */ - //.pFilePolicy = NULL + //.pFilePolicy = &filelog /* Not using file output, so NULL */ + .pFilePolicy = NULL }; if (rdk_logger_ext_init(&config) != RDK_SUCCESS) { From bdece25d9f5bf1b932f0fddc563b356dbb752027 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 7 Jul 2026 13:44:31 +0530 Subject: [PATCH 079/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 06ec9944..90065af8 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -98,8 +98,22 @@ /** Telemetry PreviousLogs scan completion sentinel — written by telemetry after it * finishes grepping PreviousLogs. Consumed by uploadstblogs as an optional gate. * Cross-repo interface: any path change MUST be coordinated with telemetry. */ +#define TELEMETRY_PREVLOGS_DONE_DIR "/tmp" +#define TELEMETRY_PREVLOGS_DONE_FILENAME ".telemetry_prevlogs_done" #define TELEMETRY_PREVLOGS_DONE_FLAG "/tmp/.telemetry_prevlogs_done" +/** Total wait timeout (seconds) for the telemetry previous-logs grep sentinel. + * For unit tests (GTEST_ENABLE) a shorter value avoids multi-minute waits. */ +#ifdef GTEST_ENABLE +#define TELEMETRY_PREVLOGS_TIMEOUT_S 2u +#else +#define TELEMETRY_PREVLOGS_TIMEOUT_S 120u +#endif + +/** Annotation code set in SessionState when telemetry prevlogs grep did not + * complete within the timeout. Upload always proceeds. */ +#define ANNOTATION_TELEMETRY_PREVLOGS_UNAVAILABLE 3 + /** Annotation code set in SessionState when NTP was not synced at upload time and * internet connectivity was absent, so the last-known-good time fallback could not * be applied. Upload always proceeds. */ From 81c2de8d651d93f72182972a71fbbdb6283aeac0 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 13:25:14 +0530 Subject: [PATCH 080/108] Update strategies.c --- uploadstblogs/src/strategies.c | 190 +++++++++------------------------ 1 file changed, 49 insertions(+), 141 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index eaf68dab..4e31f83a 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -79,7 +79,7 @@ typedef struct { size_t len; } rpc_resp_t; -static size_t internet_write_cb(void *ptr, size_t size, size_t nmemb, void *userp) +size_t internet_write_cb(void *ptr, size_t size, size_t nmemb, void *userp) { rpc_resp_t *r = (rpc_resp_t *)userp; size_t incoming = size * nmemb; @@ -91,7 +91,7 @@ static size_t internet_write_cb(void *ptr, size_t size, size_t nmemb, void *user return size * nmemb; } -static bool nm_query_ipver(const char *ipversion) +bool nm_query_ipver(const char *ipversion) { char payload[256]; CURL *ch; @@ -136,7 +136,7 @@ static bool nm_query_ipver(const char *ipversion) return (strstr(resp.buf, "NO_INTERNET") == NULL); } -static bool check_internet_connectivity(void) +bool check_internet_connectivity(void) { /* Try IPv4 first; fall back to IPv6 — mirrors iarmInterface.c */ if (nm_query_ipver("IPv4")) { return true; } @@ -154,7 +154,7 @@ static bool check_internet_connectivity(void) * * Returns the epoch (> 0) on success, 0 on any failure. */ -static time_t apply_ntp_fallback_time(void) +time_t apply_ntp_fallback_time(void) { char time_buf[32] = {0}; long epoch; @@ -202,7 +202,7 @@ static time_t apply_ntp_fallback_time(void) * * Cross-repo interface: STT_FLAG is watched by reboot-manager. */ -static void trigger_reboot_info_update(void) +void trigger_reboot_info_update(void) { struct stat st; @@ -218,50 +218,48 @@ static void trigger_reboot_info_update(void) } /** - * wait_for_reboot_reason - Wait for the reboot-reason completion sentinel. + * wait_for_sentinel - Generic inotify-based wait for a sentinel file. * - * Uses inotify to watch /tmp for creation of PATH_FLAG_INVOCATION_FILENAME - * ("Update_rebootInfo_invoked"). A select() loop with a 2-second heartbeat - * drives the wait; the total window is bounded by REBOOT_POLL_TIMEOUT_S - * measured on CLOCK_MONOTONIC so EINTR-interrupted sleeps cannot inflate the - * deadline. + * @param flag_path Full path to the sentinel file (e.g. "/tmp/.backup_logs_done") + * @param watch_dir Directory to watch (e.g. "/tmp") + * @param filename Basename of the sentinel (e.g. ".backup_logs_done") + * @param timeout_s Maximum wait in seconds (CLOCK_MONOTONIC) * - * A post-watch re-check closes the race window between the initial access() - * call and inotify_add_watch(). + * Strategy: + * 1. Fast path: sentinel already present → return 0 immediately. + * 2. Set up inotify on watch_dir for IN_CREATE | IN_MOVED_TO. + * 3. Re-check after watch is established to close the creation race window. + * 4. select() loop with 2 s heartbeat; exit when sentinel appears or + * timeout_s total seconds have elapsed. + * 5. Fallback: if inotify_init1 or inotify_add_watch fails, poll with 1 s sleep. * - * If inotify_init1 or inotify_add_watch fails the function falls back to the - * simple polling path so the upload is never silently blocked by a missing - * kernel feature. - * - * Returns 0 when the sentinel is present (previousreboot.info is ready). - * Returns -1 on timeout. A timeout does NOT abort the upload; the caller - * annotates the session and proceeds. + * Returns 0 when the sentinel is detected within the timeout. + * Returns -1 on timeout or inotify fallback timeout. */ -static int wait_for_reboot_reason(void) +int wait_for_sentinel(const char *flag_path, const char *watch_dir, const char *filename, unsigned int timeout_s) { /* Fast path: sentinel already present */ - if (access(PATH_FLAG_INVOCATION, F_OK) == 0) { + if (access(flag_path, F_OK) == 0) { return 0; } int ifd = inotify_init1(IN_CLOEXEC); if (ifd < 0) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, errno); + "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling for %s\n", + __FUNCTION__, __LINE__, errno, flag_path); } - int wd = inotify_add_watch(ifd, PATH_FLAG_INVOCATION_DIR, - IN_CREATE | IN_MOVED_TO); + int wd = inotify_add_watch(ifd, watch_dir, IN_CREATE | IN_MOVED_TO); if (wd < 0) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION_DIR, errno); + "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling for %s\n", + __FUNCTION__, __LINE__, watch_dir, errno, flag_path); close(ifd); } /* Re-check after watch is set — closes race between access() and add_watch */ - if (access(PATH_FLAG_INVOCATION, F_OK) == 0) { + if (access(flag_path, F_OK) == 0) { inotify_rm_watch(ifd, wd); close(ifd); return 0; @@ -271,12 +269,12 @@ static int wait_for_reboot_reason(void) struct timespec deadline; if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] clock_gettime failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, errno); + "[%s:%d] clock_gettime failed (errno=%d); falling back to polling for %s\n", + __FUNCTION__, __LINE__, errno, flag_path); inotify_rm_watch(ifd, wd); close(ifd); } - deadline.tv_sec += (time_t)REBOOT_POLL_TIMEOUT_S; + deadline.tv_sec += (time_t)timeout_s; int found = 0; char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; @@ -307,8 +305,7 @@ static int wait_for_reboot_reason(void) while (offset < len) { struct inotify_event *ev = (struct inotify_event *)(buf + offset); - if (ev->len > 0 && - strcmp(ev->name, PATH_FLAG_INVOCATION_FILENAME) == 0) { + if (ev->len > 0 && strcmp(ev->name, filename) == 0) { found = 1; break; } @@ -322,105 +319,19 @@ static int wait_for_reboot_reason(void) } } - -/** - * wait_for_telemetry_prevlogs_done - Wait for telemetry previous-log grep sentinel. - * - * Uses inotify to watch TELEMETRY_PREVLOGS_DONE_DIR for creation of - * TELEMETRY_PREVLOGS_DONE_FILENAME. A select() loop with a 2-second heartbeat - * drives the wait; the total window is bounded by TELEMETRY_PREVLOGS_TIMEOUT_S - * measured on CLOCK_MONOTONIC. - * - * Falls back to polling if inotify_init1 or inotify_add_watch fails. - * - * Returns 0 when the sentinel is present (telemetry grep complete). - * Returns -1 on timeout. A timeout does NOT abort the upload; the caller - * annotates the session and proceeds. - */ -static int wait_for_telemetry_prevlogs_done(void) +int wait_for_reboot_reason(void) { - /* Fast path: sentinel already present */ - if (access(TELEMETRY_PREVLOGS_DONE_FLAG, F_OK) == 0) { - return 0; - } - - int ifd = inotify_init1(IN_CLOEXEC); - if (ifd < 0) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] inotify_init1 failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, errno); - } - - int wd = inotify_add_watch(ifd, TELEMETRY_PREVLOGS_DONE_DIR, - IN_CREATE | IN_MOVED_TO); - if (wd < 0) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, TELEMETRY_PREVLOGS_DONE_DIR, errno); - close(ifd); - } - - /* Re-check after watch is set — closes race between access() and add_watch */ - if (access(TELEMETRY_PREVLOGS_DONE_FLAG, F_OK) == 0) { - inotify_rm_watch(ifd, wd); - close(ifd); - return 0; - } - - { - struct timespec deadline; - if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0) { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] clock_gettime failed (errno=%d); falling back to polling\n", - __FUNCTION__, __LINE__, errno); - inotify_rm_watch(ifd, wd); - close(ifd); - } - deadline.tv_sec += (time_t)TELEMETRY_PREVLOGS_TIMEOUT_S; - - int found = 0; - char buf[sizeof(struct inotify_event) + NAME_MAX + 1]; - - while (!found) { - struct timespec now; - if (clock_gettime(CLOCK_MONOTONIC, &now) == 0 && - now.tv_sec >= deadline.tv_sec) { - break; /* timeout */ - } - - struct timeval tv = {2, 0}; - fd_set fds; - FD_ZERO(&fds); - FD_SET(ifd, &fds); - - int ret = select(ifd + 1, &fds, NULL, NULL, &tv); - if (ret < 0) { - if (errno == EINTR) { continue; } - break; - } - if (ret == 0) { continue; } /* heartbeat — re-check deadline */ - - ssize_t len = read(ifd, buf, sizeof(buf)); - if (len <= 0) { continue; } - - ssize_t offset = 0; - while (offset < len) { - struct inotify_event *ev = - (struct inotify_event *)(buf + offset); - if (ev->len > 0 && - strcmp(ev->name, TELEMETRY_PREVLOGS_DONE_FILENAME) == 0) { - found = 1; - break; - } - offset += (ssize_t)(sizeof(struct inotify_event) + ev->len); - } - } + return wait_for_sentinel(PATH_FLAG_INVOCATION, PATH_FLAG_INVOCATION_DIR, PATH_FLAG_INVOCATION_FILENAME, REBOOT_POLL_TIMEOUT_S); +} - inotify_rm_watch(ifd, wd); - close(ifd); - return found ? 0 : -1; - } +int wait_for_ntp_sync(void) +{ + return wait_for_sentinel(STT_FLAG, STT_FLAG_DIR, STT_FLAG_FILENAME, NTP_SYNC_TIMEOUT_S); +} +int wait_for_telemetry_prevlogs_done(void) +{ + return wait_for_sentinel(TELEMETRY_PREVLOGS_DONE_FLAG, TELEMETRY_PREVLOGS_DONE_DIR, TELEMETRY_PREVLOGS_DONE_FILENAME, TELEMETRY_PREVLOGS_TIMEOUT_S); } /** @@ -1044,16 +955,15 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) bool connected = check_internet_connectivity(); if (connected) { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] NTP absent but internet available; applying last-known-good time\n", - __FUNCTION__, __LINE__); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] NTP absent but internet available; applying last-known-good time\n", __FUNCTION__, __LINE__); ctx->archive_ref_time = apply_ntp_fallback_time(); } else { - RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] NTP absent and no internet; proceeding with current system time\n", - __FUNCTION__, __LINE__); - session->upload_annotations |= (1 << ANNOTATION_NTP_UNAVAILABLE); + RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] NTP absent and no internet; proceeding with current system time\n", __FUNCTION__, __LINE__); + session->upload_annotations |= (1 << ANNOTATION_NTP_UNAVAILABLE); } + } + else { + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] NTP sync sentinel detected. Proceeding.\n", __FUNCTION__, __LINE__); } } @@ -1062,11 +972,9 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) // be done by now. Only if the sentinel is still absent after the full timeout // do we write the trigger file to nudge reboot-manager into a retry. { - RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", - __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); + RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Waiting for reboot reason sentinel %s (timeout %us)\n", __FUNCTION__, __LINE__, PATH_FLAG_INVOCATION, REBOOT_POLL_TIMEOUT_S); - if (wait_for_reboot_reason() != 0) { + if (wait_for_reboot_reason() != 0) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] Reboot reason sentinel not present after %us. " "Writing trigger to request immediate update.\n", From 406c9e9b2009b8860e0ed5f837d24f26fb40801f Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 13:26:50 +0530 Subject: [PATCH 081/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 90065af8..bab5001c 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -391,4 +391,14 @@ void t2_count_notify(char *marker); */ void t2_val_notify(char *marker, char *val); +size_t internet_write_cb(void *ptr, size_t size, size_t nmemb, void *userp); +bool nm_query_ipver(const char *ipversion); +bool check_internet_connectivity(void); +time_t apply_ntp_fallback_time(void); +void trigger_reboot_info_update(void); +int wait_for_sentinel(const char *flag_path, const char *watch_dir, const char *filename, unsigned int timeout_s); +int wait_for_reboot_reason(void); +int wait_for_ntp_sync(void); +int wait_for_telemetry_prevlogs_done(void); + #endif /* UPLOADSTBLOGS_TYPES_H */ From 226ef4039db780b55321163c71d1b6ce8e183fe3 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 13:28:26 +0530 Subject: [PATCH 082/108] Update strategies.c --- uploadstblogs/src/strategies.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 4e31f83a..5f669a76 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -70,15 +70,6 @@ static int dcm_upload(RuntimeContext* ctx, SessionState* session); static int dcm_cleanup(RuntimeContext* ctx, SessionState* session, bool upload_success); - -#define THUNDER_JSONRPC_URL "http://127.0.0.1:9998/jsonrpc" -#define INTERNET_CHECK_TIMEOUT_S 5L - -typedef struct { - char buf[512]; - size_t len; -} rpc_resp_t; - size_t internet_write_cb(void *ptr, size_t size, size_t nmemb, void *userp) { rpc_resp_t *r = (rpc_resp_t *)userp; From c00af7aac9303a593c877718d3a373ef1dabe699 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 13:29:09 +0530 Subject: [PATCH 083/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index bab5001c..6e34c52e 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -374,6 +374,14 @@ typedef struct { int upload_annotations; /**< Bitmask of ANNOTATION_* codes set during prerequisite fallback */ } SessionState; +#define THUNDER_JSONRPC_URL "http://127.0.0.1:9998/jsonrpc" +#define INTERNET_CHECK_TIMEOUT_S 5L + +typedef struct { + char buf[512]; + size_t len; +} rpc_resp_t; + /* ========================== Telemetry Helper Functions ========================== */ From 572fd09bdcc91e982b8b1a1515feb58cdfad05f5 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 13:43:40 +0530 Subject: [PATCH 084/108] Update strategies.c --- uploadstblogs/src/strategies.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 5f669a76..efd8ca39 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -315,11 +315,6 @@ int wait_for_reboot_reason(void) return wait_for_sentinel(PATH_FLAG_INVOCATION, PATH_FLAG_INVOCATION_DIR, PATH_FLAG_INVOCATION_FILENAME, REBOOT_POLL_TIMEOUT_S); } -int wait_for_ntp_sync(void) -{ - return wait_for_sentinel(STT_FLAG, STT_FLAG_DIR, STT_FLAG_FILENAME, NTP_SYNC_TIMEOUT_S); -} - int wait_for_telemetry_prevlogs_done(void) { return wait_for_sentinel(TELEMETRY_PREVLOGS_DONE_FLAG, TELEMETRY_PREVLOGS_DONE_DIR, TELEMETRY_PREVLOGS_DONE_FILENAME, TELEMETRY_PREVLOGS_TIMEOUT_S); From db61bc1681130848d83a0e2e4eb25d6baa8073ea Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:04:27 +0530 Subject: [PATCH 085/108] Update strategies_gtest.cpp --- uploadstblogs/unittest/strategies_gtest.cpp | 239 ++++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/uploadstblogs/unittest/strategies_gtest.cpp b/uploadstblogs/unittest/strategies_gtest.cpp index 38ccab8c..54ea7631 100755 --- a/uploadstblogs/unittest/strategies_gtest.cpp +++ b/uploadstblogs/unittest/strategies_gtest.cpp @@ -24,6 +24,8 @@ #include #include +#include +#include extern "C" { #include "uploadstblogs_types.h" @@ -671,6 +673,243 @@ TEST_F(StrategiesIntegrationTest, ErrorHandling_UploadFailure) { EXPECT_FALSE(session.success); // Should remain false } +// ==================== WAIT FOR SENTINEL TESTS ==================== + +class WaitForSentinelTest : public ::testing::Test { +protected: + void SetUp() override { + // Ensure g_mock_file_ops is NULL so we use real system calls + g_mock_file_ops = nullptr; + + // Create unique temp directory using PID for test isolation + snprintf(test_dir_, sizeof(test_dir_), "/tmp/sentinel_test_%d", getpid()); + mkdir(test_dir_, 0755); + + // Setup sentinel file path + snprintf(sentinel_path_, sizeof(sentinel_path_), "%s/%s", test_dir_, kSentinelName); + } + + void TearDown() override { + unlink(sentinel_path_); + rmdir(test_dir_); + } + + void CreateSentinelFile() { + int fd = open(sentinel_path_, O_CREAT | O_WRONLY, 0644); + if (fd >= 0) { + close(fd); + } + } + + void CreateFileInDir(const char* dir, const char* name) { + char path[MAX_PATH_LENGTH]; + snprintf(path, sizeof(path), "%s/%s", dir, name); + int fd = open(path, O_CREAT | O_WRONLY, 0644); + if (fd >= 0) { + close(fd); + } + } + + char test_dir_[256]; + char sentinel_path_[256]; + static constexpr const char* kSentinelName = "test_sentinel"; +}; + +/** + * @test Fast path: sentinel file already exists before wait_for_sentinel is called. + * Covers: Fast-path access() check at function entry. + */ +TEST_F(WaitForSentinelTest, FastPath_SentinelAlreadyExists) { + CreateSentinelFile(); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); + EXPECT_EQ(0, result); +} + +/** + * @test Timeout: sentinel never appears within the specified timeout. + * Covers: Full inotify loop with clock_gettime deadline expiry. + */ +TEST_F(WaitForSentinelTest, Timeout_SentinelNeverAppears) { + // Sentinel not created - should timeout after 1 second + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1); + EXPECT_EQ(-1, result); +} + +/** + * @test Inotify detection: sentinel appears after a short delay via IN_CREATE event. + * Covers: select() wakeup, read() of inotify_event, filename match. + */ +TEST_F(WaitForSentinelTest, Detection_SentinelAppearsAfterDelay) { + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + CreateSentinelFile(); + }); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); + creator.join(); + EXPECT_EQ(0, result); +} + +/** + * @test Race condition: sentinel appears between first access() and watch re-check. + * Covers: Re-check after inotify_add_watch to close the race window. + */ +TEST_F(WaitForSentinelTest, RaceCondition_SentinelAppearsDuringSetup) { + // Create sentinel with very short delay - may be caught by the re-check + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + CreateSentinelFile(); + }); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); + creator.join(); + EXPECT_EQ(0, result); +} + +/** + * @test Zero timeout: should enter loop but immediately break on deadline check. + * Covers: deadline.tv_sec += 0, immediate expiry in while loop. + */ +TEST_F(WaitForSentinelTest, ZeroTimeout_ReturnsNegativeOne) { + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 0); + EXPECT_EQ(-1, result); +} + +/** + * @test Invalid watch directory: inotify_add_watch fails on non-existent directory. + * Covers: inotify_add_watch failure path and close(ifd). + */ +TEST_F(WaitForSentinelTest, InvalidWatchDir_Timeout) { + const char* bad_dir = "/nonexistent_sentinel_test_dir_xyz"; + const char* bad_path = "/nonexistent_sentinel_test_dir_xyz/sentinel"; + + int result = wait_for_sentinel(bad_path, bad_dir, "sentinel", 1); + EXPECT_EQ(-1, result); +} + +/** + * @test Wrong filename created in watched directory - should not trigger detection. + * Covers: inotify event filename comparison (strcmp != 0 path). + */ +TEST_F(WaitForSentinelTest, WrongFilename_DoesNotMatch) { + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + // Create a file with a DIFFERENT name + CreateFileInDir(test_dir_, "not_the_sentinel"); + }); + + // Wait for "test_sentinel" which will never appear + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 2); + creator.join(); + EXPECT_EQ(-1, result); + + // Clean up the wrong file + char wrong_path[256]; + snprintf(wrong_path, sizeof(wrong_path), "%s/not_the_sentinel", test_dir_); + unlink(wrong_path); +} + +/** + * @test Multiple sequential calls with sentinel present - consistent behavior. + * Covers: Function is idempotent and has no lingering state. + */ +TEST_F(WaitForSentinelTest, MultipleCalls_ConsistentBehavior) { + CreateSentinelFile(); + + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); +} + +/** + * @test Sentinel removed then re-checked - absence detected after removal. + * Covers: Ensures no caching of previous access() results. + */ +TEST_F(WaitForSentinelTest, SentinelRemovedThenRechecked) { + CreateSentinelFile(); + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); + + // Remove sentinel + unlink(sentinel_path_); + + // Now should timeout since sentinel is gone + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1); + EXPECT_EQ(-1, result); +} + +/** + * @test wait_for_reboot_reason wrapper: sentinel present -> returns 0. + * Covers: PATH_FLAG_INVOCATION sentinel with production constants. + */ +TEST_F(WaitForSentinelTest, WaitForRebootReason_SentinelPresent) { + int fd = open(PATH_FLAG_INVOCATION, O_CREAT | O_WRONLY, 0644); + if (fd < 0) { + GTEST_SKIP() << "Cannot create " << PATH_FLAG_INVOCATION; + } + close(fd); + + int result = wait_for_reboot_reason(); + EXPECT_EQ(0, result); + + unlink(PATH_FLAG_INVOCATION); +} + +/** + * @test wait_for_reboot_reason wrapper: sentinel absent -> returns -1 after timeout. + * Covers: REBOOT_POLL_TIMEOUT_S timeout (2s in GTEST_ENABLE mode). + */ +TEST_F(WaitForSentinelTest, WaitForRebootReason_Timeout) { + unlink(PATH_FLAG_INVOCATION); + + int result = wait_for_reboot_reason(); + EXPECT_EQ(-1, result); +} + +/** + * @test wait_for_telemetry_prevlogs_done wrapper: sentinel present -> returns 0. + * Covers: TELEMETRY_PREVLOGS_DONE_FLAG with production constants. + */ +TEST_F(WaitForSentinelTest, WaitForTelemetryPrevlogsDone_SentinelPresent) { + int fd = open(TELEMETRY_PREVLOGS_DONE_FLAG, O_CREAT | O_WRONLY, 0644); + if (fd < 0) { + GTEST_SKIP() << "Cannot create " << TELEMETRY_PREVLOGS_DONE_FLAG; + } + close(fd); + + int result = wait_for_telemetry_prevlogs_done(); + EXPECT_EQ(0, result); + + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); +} + +/** + * @test wait_for_telemetry_prevlogs_done wrapper: sentinel absent -> timeout. + * Covers: TELEMETRY_PREVLOGS_TIMEOUT_S timeout (2s in GTEST_ENABLE mode). + */ +TEST_F(WaitForSentinelTest, WaitForTelemetryPrevlogsDone_Timeout) { + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); + + int result = wait_for_telemetry_prevlogs_done(); + EXPECT_EQ(-1, result); +} + +/** + * @test Sentinel appears just before timeout deadline. + * Covers: select() heartbeat re-checks and event delivery near deadline. + */ +TEST_F(WaitForSentinelTest, Detection_SentinelAppearsNearTimeout) { + // Create sentinel close to the 3s timeout (at ~2.5s) + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(2500)); + CreateSentinelFile(); + }); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 4); + creator.join(); + EXPECT_EQ(0, result); +} + // Entry point for the test executable int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From 7dbb01663058d640e36d7678cb040f98091b2c00 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:26:59 +0530 Subject: [PATCH 086/108] Update strategies_gtest.cpp --- uploadstblogs/unittest/strategies_gtest.cpp | 237 ++++++++++++++++++++ 1 file changed, 237 insertions(+) diff --git a/uploadstblogs/unittest/strategies_gtest.cpp b/uploadstblogs/unittest/strategies_gtest.cpp index 54ea7631..169d9b13 100755 --- a/uploadstblogs/unittest/strategies_gtest.cpp +++ b/uploadstblogs/unittest/strategies_gtest.cpp @@ -910,6 +910,243 @@ TEST_F(WaitForSentinelTest, Detection_SentinelAppearsNearTimeout) { EXPECT_EQ(0, result); } +// ==================== WAIT FOR SENTINEL TESTS ==================== + +class WaitForSentinelTest : public ::testing::Test { +protected: + void SetUp() override { + // Ensure g_mock_file_ops is NULL so we use real system calls + g_mock_file_ops = nullptr; + + // Create unique temp directory using PID for test isolation + snprintf(test_dir_, sizeof(test_dir_), "/tmp/sentinel_test_%d", getpid()); + mkdir(test_dir_, 0755); + + // Setup sentinel file path + snprintf(sentinel_path_, sizeof(sentinel_path_), "%s/%s", test_dir_, kSentinelName); + } + + void TearDown() override { + unlink(sentinel_path_); + rmdir(test_dir_); + } + + void CreateSentinelFile() { + int fd = open(sentinel_path_, O_CREAT | O_WRONLY, 0644); + if (fd >= 0) { + close(fd); + } + } + + void CreateFileInDir(const char* dir, const char* name) { + char path[MAX_PATH_LENGTH]; + snprintf(path, sizeof(path), "%s/%s", dir, name); + int fd = open(path, O_CREAT | O_WRONLY, 0644); + if (fd >= 0) { + close(fd); + } + } + + char test_dir_[256]; + char sentinel_path_[256]; + static constexpr const char* kSentinelName = "test_sentinel"; +}; + +/** + * @test Fast path: sentinel file already exists before wait_for_sentinel is called. + * Covers: Fast-path access() check at function entry. + */ +TEST_F(WaitForSentinelTest, FastPath_SentinelAlreadyExists) { + CreateSentinelFile(); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); + EXPECT_EQ(0, result); +} + +/** + * @test Timeout: sentinel never appears within the specified timeout. + * Covers: Full inotify loop with clock_gettime deadline expiry. + */ +TEST_F(WaitForSentinelTest, Timeout_SentinelNeverAppears) { + // Sentinel not created - should timeout after 1 second + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1); + EXPECT_EQ(-1, result); +} + +/** + * @test Inotify detection: sentinel appears after a short delay via IN_CREATE event. + * Covers: select() wakeup, read() of inotify_event, filename match. + */ +TEST_F(WaitForSentinelTest, Detection_SentinelAppearsAfterDelay) { + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + CreateSentinelFile(); + }); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); + creator.join(); + EXPECT_EQ(0, result); +} + +/** + * @test Race condition: sentinel appears between first access() and watch re-check. + * Covers: Re-check after inotify_add_watch to close the race window. + */ +TEST_F(WaitForSentinelTest, RaceCondition_SentinelAppearsDuringSetup) { + // Create sentinel with very short delay - may be caught by the re-check + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + CreateSentinelFile(); + }); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); + creator.join(); + EXPECT_EQ(0, result); +} + +/** + * @test Zero timeout: should enter loop but immediately break on deadline check. + * Covers: deadline.tv_sec += 0, immediate expiry in while loop. + */ +TEST_F(WaitForSentinelTest, ZeroTimeout_ReturnsNegativeOne) { + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 0); + EXPECT_EQ(-1, result); +} + +/** + * @test Invalid watch directory: inotify_add_watch fails on non-existent directory. + * Covers: inotify_add_watch failure path and close(ifd). + */ +TEST_F(WaitForSentinelTest, InvalidWatchDir_Timeout) { + const char* bad_dir = "/nonexistent_sentinel_test_dir_xyz"; + const char* bad_path = "/nonexistent_sentinel_test_dir_xyz/sentinel"; + + int result = wait_for_sentinel(bad_path, bad_dir, "sentinel", 1); + EXPECT_EQ(-1, result); +} + +/** + * @test Wrong filename created in watched directory - should not trigger detection. + * Covers: inotify event filename comparison (strcmp != 0 path). + */ +TEST_F(WaitForSentinelTest, WrongFilename_DoesNotMatch) { + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + // Create a file with a DIFFERENT name + CreateFileInDir(test_dir_, "not_the_sentinel"); + }); + + // Wait for "test_sentinel" which will never appear + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 2); + creator.join(); + EXPECT_EQ(-1, result); + + // Clean up the wrong file + char wrong_path[256]; + snprintf(wrong_path, sizeof(wrong_path), "%s/not_the_sentinel", test_dir_); + unlink(wrong_path); +} + +/** + * @test Multiple sequential calls with sentinel present - consistent behavior. + * Covers: Function is idempotent and has no lingering state. + */ +TEST_F(WaitForSentinelTest, MultipleCalls_ConsistentBehavior) { + CreateSentinelFile(); + + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); +} + +/** + * @test Sentinel removed then re-checked - absence detected after removal. + * Covers: Ensures no caching of previous access() results. + */ +TEST_F(WaitForSentinelTest, SentinelRemovedThenRechecked) { + CreateSentinelFile(); + EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); + + // Remove sentinel + unlink(sentinel_path_); + + // Now should timeout since sentinel is gone + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1); + EXPECT_EQ(-1, result); +} + +/** + * @test wait_for_reboot_reason wrapper: sentinel present -> returns 0. + * Covers: PATH_FLAG_INVOCATION sentinel with production constants. + */ +TEST_F(WaitForSentinelTest, WaitForRebootReason_SentinelPresent) { + int fd = open(PATH_FLAG_INVOCATION, O_CREAT | O_WRONLY, 0644); + if (fd < 0) { + GTEST_SKIP() << "Cannot create " << PATH_FLAG_INVOCATION; + } + close(fd); + + int result = wait_for_reboot_reason(); + EXPECT_EQ(0, result); + + unlink(PATH_FLAG_INVOCATION); +} + +/** + * @test wait_for_reboot_reason wrapper: sentinel absent -> returns -1 after timeout. + * Covers: REBOOT_POLL_TIMEOUT_S timeout (2s in GTEST_ENABLE mode). + */ +TEST_F(WaitForSentinelTest, WaitForRebootReason_Timeout) { + unlink(PATH_FLAG_INVOCATION); + + int result = wait_for_reboot_reason(); + EXPECT_EQ(-1, result); +} + +/** + * @test wait_for_telemetry_prevlogs_done wrapper: sentinel present -> returns 0. + * Covers: TELEMETRY_PREVLOGS_DONE_FLAG with production constants. + */ +TEST_F(WaitForSentinelTest, WaitForTelemetryPrevlogsDone_SentinelPresent) { + int fd = open(TELEMETRY_PREVLOGS_DONE_FLAG, O_CREAT | O_WRONLY, 0644); + if (fd < 0) { + GTEST_SKIP() << "Cannot create " << TELEMETRY_PREVLOGS_DONE_FLAG; + } + close(fd); + + int result = wait_for_telemetry_prevlogs_done(); + EXPECT_EQ(0, result); + + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); +} + +/** + * @test wait_for_telemetry_prevlogs_done wrapper: sentinel absent -> timeout. + * Covers: TELEMETRY_PREVLOGS_TIMEOUT_S timeout (2s in GTEST_ENABLE mode). + */ +TEST_F(WaitForSentinelTest, WaitForTelemetryPrevlogsDone_Timeout) { + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); + + int result = wait_for_telemetry_prevlogs_done(); + EXPECT_EQ(-1, result); +} + +/** + * @test Sentinel appears just before timeout deadline. + * Covers: select() heartbeat re-checks and event delivery near deadline. + */ +TEST_F(WaitForSentinelTest, Detection_SentinelAppearsNearTimeout) { + // Create sentinel close to the 3s timeout (at ~2.5s) + std::thread creator([this]() { + std::this_thread::sleep_for(std::chrono::milliseconds(2500)); + CreateSentinelFile(); + }); + + int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 4); + creator.join(); + EXPECT_EQ(0, result); +} + // Entry point for the test executable int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From 331c3d9a3c34f6224eb9e0e5951248b6f89fe0ee Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:28:01 +0530 Subject: [PATCH 087/108] Update strategies_gtest.cpp --- uploadstblogs/unittest/strategies_gtest.cpp | 237 -------------------- 1 file changed, 237 deletions(-) diff --git a/uploadstblogs/unittest/strategies_gtest.cpp b/uploadstblogs/unittest/strategies_gtest.cpp index 169d9b13..54ea7631 100755 --- a/uploadstblogs/unittest/strategies_gtest.cpp +++ b/uploadstblogs/unittest/strategies_gtest.cpp @@ -910,243 +910,6 @@ TEST_F(WaitForSentinelTest, Detection_SentinelAppearsNearTimeout) { EXPECT_EQ(0, result); } -// ==================== WAIT FOR SENTINEL TESTS ==================== - -class WaitForSentinelTest : public ::testing::Test { -protected: - void SetUp() override { - // Ensure g_mock_file_ops is NULL so we use real system calls - g_mock_file_ops = nullptr; - - // Create unique temp directory using PID for test isolation - snprintf(test_dir_, sizeof(test_dir_), "/tmp/sentinel_test_%d", getpid()); - mkdir(test_dir_, 0755); - - // Setup sentinel file path - snprintf(sentinel_path_, sizeof(sentinel_path_), "%s/%s", test_dir_, kSentinelName); - } - - void TearDown() override { - unlink(sentinel_path_); - rmdir(test_dir_); - } - - void CreateSentinelFile() { - int fd = open(sentinel_path_, O_CREAT | O_WRONLY, 0644); - if (fd >= 0) { - close(fd); - } - } - - void CreateFileInDir(const char* dir, const char* name) { - char path[MAX_PATH_LENGTH]; - snprintf(path, sizeof(path), "%s/%s", dir, name); - int fd = open(path, O_CREAT | O_WRONLY, 0644); - if (fd >= 0) { - close(fd); - } - } - - char test_dir_[256]; - char sentinel_path_[256]; - static constexpr const char* kSentinelName = "test_sentinel"; -}; - -/** - * @test Fast path: sentinel file already exists before wait_for_sentinel is called. - * Covers: Fast-path access() check at function entry. - */ -TEST_F(WaitForSentinelTest, FastPath_SentinelAlreadyExists) { - CreateSentinelFile(); - - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); - EXPECT_EQ(0, result); -} - -/** - * @test Timeout: sentinel never appears within the specified timeout. - * Covers: Full inotify loop with clock_gettime deadline expiry. - */ -TEST_F(WaitForSentinelTest, Timeout_SentinelNeverAppears) { - // Sentinel not created - should timeout after 1 second - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1); - EXPECT_EQ(-1, result); -} - -/** - * @test Inotify detection: sentinel appears after a short delay via IN_CREATE event. - * Covers: select() wakeup, read() of inotify_event, filename match. - */ -TEST_F(WaitForSentinelTest, Detection_SentinelAppearsAfterDelay) { - std::thread creator([this]() { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - CreateSentinelFile(); - }); - - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); - creator.join(); - EXPECT_EQ(0, result); -} - -/** - * @test Race condition: sentinel appears between first access() and watch re-check. - * Covers: Re-check after inotify_add_watch to close the race window. - */ -TEST_F(WaitForSentinelTest, RaceCondition_SentinelAppearsDuringSetup) { - // Create sentinel with very short delay - may be caught by the re-check - std::thread creator([this]() { - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - CreateSentinelFile(); - }); - - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 5); - creator.join(); - EXPECT_EQ(0, result); -} - -/** - * @test Zero timeout: should enter loop but immediately break on deadline check. - * Covers: deadline.tv_sec += 0, immediate expiry in while loop. - */ -TEST_F(WaitForSentinelTest, ZeroTimeout_ReturnsNegativeOne) { - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 0); - EXPECT_EQ(-1, result); -} - -/** - * @test Invalid watch directory: inotify_add_watch fails on non-existent directory. - * Covers: inotify_add_watch failure path and close(ifd). - */ -TEST_F(WaitForSentinelTest, InvalidWatchDir_Timeout) { - const char* bad_dir = "/nonexistent_sentinel_test_dir_xyz"; - const char* bad_path = "/nonexistent_sentinel_test_dir_xyz/sentinel"; - - int result = wait_for_sentinel(bad_path, bad_dir, "sentinel", 1); - EXPECT_EQ(-1, result); -} - -/** - * @test Wrong filename created in watched directory - should not trigger detection. - * Covers: inotify event filename comparison (strcmp != 0 path). - */ -TEST_F(WaitForSentinelTest, WrongFilename_DoesNotMatch) { - std::thread creator([this]() { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - // Create a file with a DIFFERENT name - CreateFileInDir(test_dir_, "not_the_sentinel"); - }); - - // Wait for "test_sentinel" which will never appear - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 2); - creator.join(); - EXPECT_EQ(-1, result); - - // Clean up the wrong file - char wrong_path[256]; - snprintf(wrong_path, sizeof(wrong_path), "%s/not_the_sentinel", test_dir_); - unlink(wrong_path); -} - -/** - * @test Multiple sequential calls with sentinel present - consistent behavior. - * Covers: Function is idempotent and has no lingering state. - */ -TEST_F(WaitForSentinelTest, MultipleCalls_ConsistentBehavior) { - CreateSentinelFile(); - - EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); - EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); - EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); -} - -/** - * @test Sentinel removed then re-checked - absence detected after removal. - * Covers: Ensures no caching of previous access() results. - */ -TEST_F(WaitForSentinelTest, SentinelRemovedThenRechecked) { - CreateSentinelFile(); - EXPECT_EQ(0, wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1)); - - // Remove sentinel - unlink(sentinel_path_); - - // Now should timeout since sentinel is gone - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 1); - EXPECT_EQ(-1, result); -} - -/** - * @test wait_for_reboot_reason wrapper: sentinel present -> returns 0. - * Covers: PATH_FLAG_INVOCATION sentinel with production constants. - */ -TEST_F(WaitForSentinelTest, WaitForRebootReason_SentinelPresent) { - int fd = open(PATH_FLAG_INVOCATION, O_CREAT | O_WRONLY, 0644); - if (fd < 0) { - GTEST_SKIP() << "Cannot create " << PATH_FLAG_INVOCATION; - } - close(fd); - - int result = wait_for_reboot_reason(); - EXPECT_EQ(0, result); - - unlink(PATH_FLAG_INVOCATION); -} - -/** - * @test wait_for_reboot_reason wrapper: sentinel absent -> returns -1 after timeout. - * Covers: REBOOT_POLL_TIMEOUT_S timeout (2s in GTEST_ENABLE mode). - */ -TEST_F(WaitForSentinelTest, WaitForRebootReason_Timeout) { - unlink(PATH_FLAG_INVOCATION); - - int result = wait_for_reboot_reason(); - EXPECT_EQ(-1, result); -} - -/** - * @test wait_for_telemetry_prevlogs_done wrapper: sentinel present -> returns 0. - * Covers: TELEMETRY_PREVLOGS_DONE_FLAG with production constants. - */ -TEST_F(WaitForSentinelTest, WaitForTelemetryPrevlogsDone_SentinelPresent) { - int fd = open(TELEMETRY_PREVLOGS_DONE_FLAG, O_CREAT | O_WRONLY, 0644); - if (fd < 0) { - GTEST_SKIP() << "Cannot create " << TELEMETRY_PREVLOGS_DONE_FLAG; - } - close(fd); - - int result = wait_for_telemetry_prevlogs_done(); - EXPECT_EQ(0, result); - - unlink(TELEMETRY_PREVLOGS_DONE_FLAG); -} - -/** - * @test wait_for_telemetry_prevlogs_done wrapper: sentinel absent -> timeout. - * Covers: TELEMETRY_PREVLOGS_TIMEOUT_S timeout (2s in GTEST_ENABLE mode). - */ -TEST_F(WaitForSentinelTest, WaitForTelemetryPrevlogsDone_Timeout) { - unlink(TELEMETRY_PREVLOGS_DONE_FLAG); - - int result = wait_for_telemetry_prevlogs_done(); - EXPECT_EQ(-1, result); -} - -/** - * @test Sentinel appears just before timeout deadline. - * Covers: select() heartbeat re-checks and event delivery near deadline. - */ -TEST_F(WaitForSentinelTest, Detection_SentinelAppearsNearTimeout) { - // Create sentinel close to the 3s timeout (at ~2.5s) - std::thread creator([this]() { - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - CreateSentinelFile(); - }); - - int result = wait_for_sentinel(sentinel_path_, test_dir_, kSentinelName, 4); - creator.join(); - EXPECT_EQ(0, result); -} - // Entry point for the test executable int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From 24c511b1763ebbf56101fab48b5b2cb8410e4b85 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:42:03 +0530 Subject: [PATCH 088/108] Update backup_logs.c --- backup_logs/src/backup_logs.c | 53 ----------------------------------- 1 file changed, 53 deletions(-) diff --git a/backup_logs/src/backup_logs.c b/backup_logs/src/backup_logs.c index b1114794..b0ad815f 100644 --- a/backup_logs/src/backup_logs.c +++ b/backup_logs/src/backup_logs.c @@ -279,16 +279,6 @@ int backup_logs_main(int argc, char *argv[]) { static backup_config_t config; memset(&config, 0, sizeof(config)); - /* Record monotonic start time for elapsed-time measurements */ - struct timespec start_time; - clock_gettime(CLOCK_MONOTONIC, &start_time); - { - time_t now = time(NULL); - struct tm *tm_info = localtime(&now); - char wall_ts[32]; - strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); - RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "backup_logs start wall-clock time: %s\n", wall_ts); - } /* Initialize backup system */ RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Initializing backup system\n"); @@ -297,23 +287,6 @@ int backup_logs_main(int argc, char *argv[]) { RDK_LOG(RDK_LOG_ERROR, LOG_BACKUP_LOGS, "Failed to initialize backup system with result: %d\n", result); return EXIT_FAILURE; } - - /* Execute backup process */ - - { - struct timespec exec_ts; - clock_gettime(CLOCK_MONOTONIC, &exec_ts); - long el_sec = (long)(exec_ts.tv_sec - start_time.tv_sec); - long el_msec = (exec_ts.tv_nsec - start_time.tv_nsec) / 1000000L; - if (el_msec < 0) { el_sec--; el_msec += 1000L; } - time_t wall = time(NULL); - struct tm *tm_info = localtime(&wall); - char wall_ts[32]; - strftime(wall_ts, sizeof(wall_ts), "%Y-%m-%dT%H:%M:%S", tm_info); - RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, - "Backup execution start wall-clock time: %s (elapsed since backup_logs start: %lds %ldms)\n", - wall_ts, el_sec, el_msec); - } RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Starting backup execution\n"); result = backup_logs_execute(&config); @@ -323,22 +296,6 @@ int backup_logs_main(int argc, char *argv[]) { return EXIT_FAILURE; } - { - struct timespec done_ts; - clock_gettime(CLOCK_MONOTONIC, &done_ts); - long el_sec = (long)(done_ts.tv_sec - start_time.tv_sec); - long el_msec = (done_ts.tv_nsec - start_time.tv_nsec) / 1000000L; - if (el_msec < 0) { el_sec--; el_msec += 1000L; } - if (result != BACKUP_SUCCESS) { - RDK_LOG(RDK_LOG_ERROR, LOG_BACKUP_LOGS, - "Backup execution failed with result: %d (elapsed since backup_logs start: %lds %ldms)\n", - result, el_sec, el_msec); - } else { - RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, - "Backup execution completed successfully (elapsed since backup_logs start: %lds %ldms)\n", - el_sec, el_msec); - } - } /* Cleanup and exit */ RDK_LOG(RDK_LOG_DEBUG, LOG_BACKUP_LOGS, "Starting cleanup and shutdown\n"); @@ -365,16 +322,6 @@ int backup_logs_main(int argc, char *argv[]) { } } - { - struct timespec final_ts; - clock_gettime(CLOCK_MONOTONIC, &final_ts); - long el_sec = (long)(final_ts.tv_sec - start_time.tv_sec); - long el_msec = (final_ts.tv_nsec - start_time.tv_nsec) / 1000000L; - if (el_msec < 0) { el_sec--; el_msec += 1000L; } - RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, - "Backup process completed successfully (total elapsed: %lds %ldms)\n", - el_sec, el_msec); - } return EXIT_SUCCESS; } #ifndef GTEST_ENABLE From b248a90844fd37d675880f3b206dff307666deb2 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:10:28 +0530 Subject: [PATCH 089/108] Update strategies_gtest.cpp --- uploadstblogs/unittest/strategies_gtest.cpp | 36 +++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/uploadstblogs/unittest/strategies_gtest.cpp b/uploadstblogs/unittest/strategies_gtest.cpp index 54ea7631..6b494826 100755 --- a/uploadstblogs/unittest/strategies_gtest.cpp +++ b/uploadstblogs/unittest/strategies_gtest.cpp @@ -560,9 +560,25 @@ class StrategyRebootTest : public ::testing::Test { memset(&session, 0, sizeof(session)); strcpy(session.archive_file, "reboot_logs.tar.gz"); session.success = false; + + // Create sentinel files required by reboot_setup prerequisites + CreateSentinel(BACKUP_LOGS_DONE_FLAG); + CreateSentinel(STT_FLAG); + CreateSentinel(PATH_FLAG_INVOCATION); + CreateSentinel(TELEMETRY_PREVLOGS_DONE_FLAG); } - void TearDown() override {} + void TearDown() override { + unlink(BACKUP_LOGS_DONE_FLAG); + unlink(STT_FLAG); + unlink(PATH_FLAG_INVOCATION); + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); + } + + void CreateSentinel(const char* path) { + int fd = open(path, O_CREAT | O_WRONLY, 0644); + if (fd >= 0) close(fd); + } RuntimeContext ctx; SessionState session; @@ -630,9 +646,25 @@ class StrategiesIntegrationTest : public ::testing::Test { // Initialize common session memset(&session, 0, sizeof(session)); session.success = false; + + // Create sentinel files required by reboot_setup prerequisites + CreateSentinel(BACKUP_LOGS_DONE_FLAG); + CreateSentinel(STT_FLAG); + CreateSentinel(PATH_FLAG_INVOCATION); + CreateSentinel(TELEMETRY_PREVLOGS_DONE_FLAG); } - void TearDown() override {} + void TearDown() override { + unlink(BACKUP_LOGS_DONE_FLAG); + unlink(STT_FLAG); + unlink(PATH_FLAG_INVOCATION); + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); + } + + void CreateSentinel(const char* path) { + int fd = open(path, O_CREAT | O_WRONLY, 0644); + if (fd >= 0) close(fd); + } RuntimeContext ctx; SessionState session; From 8ac4853720a7818ad0239a2076bdabf135b1ecbe Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:31:37 +0530 Subject: [PATCH 090/108] Update strategies_gtest.cpp --- uploadstblogs/unittest/strategies_gtest.cpp | 256 ++++++++++++++++++++ 1 file changed, 256 insertions(+) diff --git a/uploadstblogs/unittest/strategies_gtest.cpp b/uploadstblogs/unittest/strategies_gtest.cpp index 6b494826..9c724674 100755 --- a/uploadstblogs/unittest/strategies_gtest.cpp +++ b/uploadstblogs/unittest/strategies_gtest.cpp @@ -942,6 +942,262 @@ TEST_F(WaitForSentinelTest, Detection_SentinelAppearsNearTimeout) { EXPECT_EQ(0, result); } +// ==================== HELPER FUNCTION TESTS ==================== + +/** + * Test fixture for internet_write_cb, nm_query_ipver, check_internet_connectivity, + * apply_ntp_fallback_time, and trigger_reboot_info_update. + */ +class HelperFunctionsTest : public ::testing::Test { +protected: + void SetUp() override { + g_mock_file_ops = nullptr; + } + + void TearDown() override { + g_mock_file_ops = nullptr; + } + + void CreateFile(const char* path) { + int fd = open(path, O_CREAT | O_WRONLY, 0644); + if (fd >= 0) close(fd); + } +}; + +// ---- internet_write_cb tests ---- + +/** + * @test Normal write: data fits entirely in buffer. + * Covers: memcpy path, len update, null terminator. + */ +TEST_F(HelperFunctionsTest, InternetWriteCb_NormalWrite) { + rpc_resp_t resp; + memset(&resp, 0, sizeof(resp)); + + const char* data = "Hello, World!"; + size_t ret = internet_write_cb((void*)data, 1, strlen(data), &resp); + + EXPECT_EQ(ret, strlen(data)); + EXPECT_EQ(resp.len, strlen(data)); + EXPECT_STREQ(resp.buf, "Hello, World!"); +} + +/** + * @test Multiple sequential writes accumulate in buffer. + * Covers: Appending to existing content via r->len offset. + */ +TEST_F(HelperFunctionsTest, InternetWriteCb_MultipleWrites) { + rpc_resp_t resp; + memset(&resp, 0, sizeof(resp)); + + const char* part1 = "Hello"; + const char* part2 = ", World!"; + internet_write_cb((void*)part1, 1, strlen(part1), &resp); + internet_write_cb((void*)part2, 1, strlen(part2), &resp); + + EXPECT_EQ(resp.len, strlen("Hello, World!")); + EXPECT_STREQ(resp.buf, "Hello, World!"); +} + +/** + * @test Buffer overflow protection: data larger than remaining space is truncated. + * Covers: incoming > space clamp, return value still reports full size*nmemb. + */ +TEST_F(HelperFunctionsTest, InternetWriteCb_BufferOverflowProtection) { + rpc_resp_t resp; + memset(&resp, 0, sizeof(resp)); + + // Fill buffer almost to capacity (leave 5 bytes + null) + resp.len = sizeof(resp.buf) - 6; + memset(resp.buf, 'A', resp.len); + + const char* overflow_data = "OVERFLOW_DATA_THAT_IS_TOO_LONG"; + size_t ret = internet_write_cb((void*)overflow_data, 1, strlen(overflow_data), &resp); + + // Return value is always size*nmemb (curl convention) + EXPECT_EQ(ret, strlen(overflow_data)); + // Buffer should only contain what fits (5 chars + null) + EXPECT_EQ(resp.len, sizeof(resp.buf) - 1); + // Null terminated + EXPECT_EQ(resp.buf[resp.len], '\0'); +} + +/** + * @test Zero-length write returns 0. + * Covers: size*nmemb == 0 edge case. + */ +TEST_F(HelperFunctionsTest, InternetWriteCb_ZeroLength) { + rpc_resp_t resp; + memset(&resp, 0, sizeof(resp)); + + size_t ret = internet_write_cb((void*)"data", 0, 0, &resp); + + EXPECT_EQ(ret, 0u); + EXPECT_EQ(resp.len, 0u); + EXPECT_EQ(resp.buf[0], '\0'); +} + +/** + * @test size != 1: verifies size*nmemb calculation. + * Covers: Curl may pass size=sizeof(element), nmemb=count. + */ +TEST_F(HelperFunctionsTest, InternetWriteCb_SizeTimesNmemb) { + rpc_resp_t resp; + memset(&resp, 0, sizeof(resp)); + + const char data[] = "ABCDEF"; + // size=2, nmemb=3 → total 6 bytes + size_t ret = internet_write_cb((void*)data, 2, 3, &resp); + + EXPECT_EQ(ret, 6u); + EXPECT_EQ(resp.len, 6u); + EXPECT_EQ(memcmp(resp.buf, "ABCDEF", 6), 0); +} + +// ---- check_internet_connectivity / nm_query_ipver tests ---- + +/** + * @test check_internet_connectivity returns false when Thunder is unreachable. + * Covers: curl_easy_perform failure path (CURLE_COULDNT_CONNECT in CI). + * Note: In Docker CI, nothing listens on 127.0.0.1:9998. + */ +TEST_F(HelperFunctionsTest, CheckInternetConnectivity_NoThunder) { + // In CI/test environment, Thunder JSON-RPC is not running + bool result = check_internet_connectivity(); + EXPECT_FALSE(result); +} + +/** + * @test nm_query_ipver returns false when Thunder is unreachable (IPv4). + * Covers: curl_easy_perform → CURLE_COULDNT_CONNECT → returns false. + */ +TEST_F(HelperFunctionsTest, NmQueryIpver_IPv4_NoThunder) { + bool result = nm_query_ipver("IPv4"); + EXPECT_FALSE(result); +} + +/** + * @test nm_query_ipver returns false when Thunder is unreachable (IPv6). + * Covers: Same failure path for IPv6 variant. + */ +TEST_F(HelperFunctionsTest, NmQueryIpver_IPv6_NoThunder) { + bool result = nm_query_ipver("IPv6"); + EXPECT_FALSE(result); +} + +// ---- apply_ntp_fallback_time tests ---- + +/** + * @test apply_ntp_fallback_time returns 0 when clock file is unreadable. + * Covers: fopen returns NULL path (mocked fopen returns nullptr when g_mock_file_ops is NULL). + */ +TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_FileNotReadable) { + // With g_mock_file_ops = nullptr, fopen always returns nullptr + time_t result = apply_ntp_fallback_time(); + EXPECT_EQ(result, 0); +} + +// ---- trigger_reboot_info_update tests ---- + +/** + * @test trigger_reboot_info_update does nothing when PATH_FLAG_INVOCATION exists. + * Covers: stat(PATH_FLAG_INVOCATION) succeeds → no STT_FLAG touch. + */ +TEST_F(HelperFunctionsTest, TriggerRebootInfoUpdate_FlagAlreadyPresent) { + // Create PATH_FLAG_INVOCATION so stat() succeeds + CreateFile(PATH_FLAG_INVOCATION); + // Remove STT_FLAG to verify it's NOT created + unlink(STT_FLAG); + + trigger_reboot_info_update(); + + // STT_FLAG should NOT be created since PATH_FLAG_INVOCATION exists + struct stat st; + EXPECT_NE(stat(STT_FLAG, &st), 0); + + unlink(PATH_FLAG_INVOCATION); +} + +/** + * @test trigger_reboot_info_update creates STT_FLAG when PATH_FLAG_INVOCATION absent. + * Covers: stat(PATH_FLAG_INVOCATION) fails → open(STT_FLAG) path. + */ +TEST_F(HelperFunctionsTest, TriggerRebootInfoUpdate_CreatesSTTFlag) { + // Ensure PATH_FLAG_INVOCATION does NOT exist + unlink(PATH_FLAG_INVOCATION); + // Ensure STT_FLAG does NOT exist + unlink(STT_FLAG); + + trigger_reboot_info_update(); + + // STT_FLAG should now exist + struct stat st; + EXPECT_EQ(stat(STT_FLAG, &st), 0); + + // Cleanup + unlink(STT_FLAG); +} + +// ---- wait_for_reboot_reason / wait_for_telemetry_prevlogs_done ---- +// (Additional tests beyond WaitForSentinelTest fixture) + +/** + * @test wait_for_reboot_reason uses correct constants. + * Covers: Verifies PATH_FLAG_INVOCATION constant by creating it and checking return. + */ +TEST_F(HelperFunctionsTest, WaitForRebootReason_UsesCorrectPath) { + CreateFile(PATH_FLAG_INVOCATION); + + int result = wait_for_reboot_reason(); + EXPECT_EQ(0, result); + + unlink(PATH_FLAG_INVOCATION); +} + +/** + * @test wait_for_telemetry_prevlogs_done uses correct constants. + * Covers: Verifies TELEMETRY_PREVLOGS_DONE_FLAG constant. + */ +TEST_F(HelperFunctionsTest, WaitForTelemetryPrevlogsDone_UsesCorrectPath) { + CreateFile(TELEMETRY_PREVLOGS_DONE_FLAG); + + int result = wait_for_telemetry_prevlogs_done(); + EXPECT_EQ(0, result); + + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); +} + +/** + * @test wait_for_reboot_reason timeout is short in GTEST_ENABLE mode. + * Covers: REBOOT_POLL_TIMEOUT_S == 2 when GTEST_ENABLE defined. + */ +TEST_F(HelperFunctionsTest, WaitForRebootReason_ShortTimeoutInTest) { + unlink(PATH_FLAG_INVOCATION); + + auto start = std::chrono::steady_clock::now(); + int result = wait_for_reboot_reason(); + auto elapsed = std::chrono::steady_clock::now() - start; + + EXPECT_EQ(-1, result); + // Should complete within ~3s (2s timeout + select heartbeat) + EXPECT_LT(std::chrono::duration_cast(elapsed).count(), 5); +} + +/** + * @test wait_for_telemetry_prevlogs_done timeout is short in GTEST_ENABLE mode. + * Covers: TELEMETRY_PREVLOGS_TIMEOUT_S == 2 when GTEST_ENABLE defined. + */ +TEST_F(HelperFunctionsTest, WaitForTelemetryPrevlogsDone_ShortTimeoutInTest) { + unlink(TELEMETRY_PREVLOGS_DONE_FLAG); + + auto start = std::chrono::steady_clock::now(); + int result = wait_for_telemetry_prevlogs_done(); + auto elapsed = std::chrono::steady_clock::now() - start; + + EXPECT_EQ(-1, result); + EXPECT_LT(std::chrono::duration_cast(elapsed).count(), 5); +} + // Entry point for the test executable int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); From 64189744f4ed3852240e462469649f34311610b0 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:35:59 +0530 Subject: [PATCH 091/108] Update archive_manager_gtest.cpp --- .../unittest/archive_manager_gtest.cpp | 63 ++++++------------- 1 file changed, 20 insertions(+), 43 deletions(-) diff --git a/uploadstblogs/unittest/archive_manager_gtest.cpp b/uploadstblogs/unittest/archive_manager_gtest.cpp index e647dc01..dab9fa20 100755 --- a/uploadstblogs/unittest/archive_manager_gtest.cpp +++ b/uploadstblogs/unittest/archive_manager_gtest.cpp @@ -22,11 +22,6 @@ #include #include #include -#include - -#define GTEST_DEFAULT_RESULT_FILEPATH "/tmp/Gtest_Report/" -#define GTEST_DEFAULT_RESULT_FILENAME "archive_manager_gtest_report.json" -#define GTEST_REPORT_FILEPATH_SIZE 256 // Mock RDK_LOG before including other headers #ifdef GTEST_ENABLE @@ -88,16 +83,10 @@ static int g_fread_call_count = 0; // Global counter for fread calls per file // Helper function to detect if this is a test-related file we should mock // Mock implementations FILE* fopen(const char* filename, const char* mode) { - if (!filename) return nullptr; - // Delegate to real fopen for system files and GTest output files to prevent - // crashes when GTest writes its JSON report using the fake mock FILE pointer. - if (strstr(filename, "log4c") || strstr(filename, "rdk_debug") || - strstr(filename, "/etc/") || strstr(filename, "/usr/") || - strstr(filename, GTEST_DEFAULT_RESULT_FILEPATH) || strstr(filename, ".json")) { - typedef FILE* (*real_fopen_t)(const char*, const char*); - static real_fopen_t real_fopen = nullptr; - if (!real_fopen) real_fopen = (real_fopen_t)dlsym(RTLD_NEXT, "fopen"); - return real_fopen ? real_fopen(filename, mode) : nullptr; + // Don't mock system library files - return nullptr to prevent crashes + if (!filename || strstr(filename, "log4c") || strstr(filename, "rdk_debug") || + strstr(filename, "/etc/") || strstr(filename, "/usr/")) { + return nullptr; } if (strstr(filename, "fail")) return nullptr; g_fread_call_count = 0; @@ -109,11 +98,7 @@ int fclose(FILE* stream) { g_fread_call_count = 0; return 0; } - // Delegate to real fclose for real FILE handles (e.g., GTest output files) - typedef int (*real_fclose_t)(FILE*); - static real_fclose_t real_fclose = nullptr; - if (!real_fclose) real_fclose = (real_fclose_t)dlsym(RTLD_NEXT, "fclose"); - return (real_fclose && stream) ? real_fclose(stream) : -1; + return -1; } size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { @@ -131,14 +116,8 @@ size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { } size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) { - if (stream == mock_file_ptr) { - return ptr ? nmemb : 0; - } - // Delegate to real fwrite for real FILE handles (e.g., gcov .gcda profiling output) - typedef size_t (*real_fwrite_t)(const void*, size_t, size_t, FILE*); - static real_fwrite_t real_fwrite = nullptr; - if (!real_fwrite) real_fwrite = (real_fwrite_t)dlsym(RTLD_NEXT, "fwrite"); - return (real_fwrite && ptr && stream) ? real_fwrite(ptr, size, nmemb, stream) : 0; + if (stream != mock_file_ptr || !ptr) return 0; + return nmemb; } int stat(const char* path, struct stat* buf) { @@ -344,15 +323,15 @@ TEST_F(ArchiveManagerTest, ArchiveNameGeneration_RemovesColons) { } TEST_F(ArchiveManagerTest, ArchiveNameGeneration_EmptyMAC) { - // Empty MAC should be handled gracefully + // Empty MAC should be handled gracefully - generates name with empty MAC prefix strcpy(ctx.mac_address, ""); EXPECT_CALL(*g_mockFileOperations, dir_exists(_)) .WillRepeatedly(Return(true)); int ret = create_archive(&ctx, &session, "/tmp"); - // Should fail when MAC is empty - EXPECT_EQ(ret, -1); + // Function succeeds; empty MAC results in filename like "_Logs_.tgz" + EXPECT_EQ(ret, 0); } // Test get_archive_size function @@ -692,17 +671,15 @@ TEST_F(ArchiveManagerTest, CollectDriLogs_Success) { EXPECT_GE(result, 0); } -GTEST_API_ int main(int argc, char *argv[]){ - char testresults_fullfilepath[GTEST_REPORT_FILEPATH_SIZE]; - char buffer[GTEST_REPORT_FILEPATH_SIZE]; - - memset( testresults_fullfilepath, 0, GTEST_REPORT_FILEPATH_SIZE ); - memset( buffer, 0, GTEST_REPORT_FILEPATH_SIZE ); - - snprintf( testresults_fullfilepath, GTEST_REPORT_FILEPATH_SIZE, "json:%s%s" , GTEST_DEFAULT_RESULT_FILEPATH , GTEST_DEFAULT_RESULT_FILENAME); - ::testing::GTEST_FLAG(output) = testresults_fullfilepath; +int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - //testing::Mock::AllowLeak(mock); - return RUN_ALL_TESTS(); + int result = RUN_ALL_TESTS(); + + // Ensure global mock is cleaned up + if (g_mockFileOperations) { + delete g_mockFileOperations; + g_mockFileOperations = nullptr; + } + + return result; } - From 0e1b1d119d2b27e657a99af57170456298ddff1a Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:49:50 +0530 Subject: [PATCH 092/108] Update backup_logs.c --- backup_logs/src/backup_logs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/backup_logs/src/backup_logs.c b/backup_logs/src/backup_logs.c index b0ad815f..afd76037 100644 --- a/backup_logs/src/backup_logs.c +++ b/backup_logs/src/backup_logs.c @@ -279,7 +279,6 @@ int backup_logs_main(int argc, char *argv[]) { static backup_config_t config; memset(&config, 0, sizeof(config)); - /* Initialize backup system */ RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Initializing backup system\n"); result = backup_logs_init(&config); From 251db2be173370a4c3455cf95cf7371644fa04cc Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:50:54 +0530 Subject: [PATCH 093/108] Update backup_logs.c --- backup_logs/src/backup_logs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backup_logs/src/backup_logs.c b/backup_logs/src/backup_logs.c index afd76037..601882da 100644 --- a/backup_logs/src/backup_logs.c +++ b/backup_logs/src/backup_logs.c @@ -286,7 +286,8 @@ int backup_logs_main(int argc, char *argv[]) { RDK_LOG(RDK_LOG_ERROR, LOG_BACKUP_LOGS, "Failed to initialize backup system with result: %d\n", result); return EXIT_FAILURE; } - + + /* Execute backup process */ RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Starting backup execution\n"); result = backup_logs_execute(&config); if (result != BACKUP_SUCCESS) { From 0d68fe27f377e655a0d74da969e8f5039a4b97a0 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:58:15 +0530 Subject: [PATCH 094/108] Update dcm_gtest.cpp --- unittest/dcm_gtest.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/unittest/dcm_gtest.cpp b/unittest/dcm_gtest.cpp index 62b10f91..1ab473b4 100644 --- a/unittest/dcm_gtest.cpp +++ b/unittest/dcm_gtest.cpp @@ -91,9 +91,6 @@ class DcmDaemonMainInitTest : public ::testing::Test { if (dcmHandle.pRbusHandle) { dcmRbusUnInit(dcmHandle.pRbusHandle); } - if (dcmHandle.pLogSchedHandle) { - dcmSchedRemoveJob(dcmHandle.pLogSchedHandle); - } if (dcmHandle.pDifdSchedHandle) { dcmSchedRemoveJob(dcmHandle.pDifdSchedHandle); } @@ -146,7 +143,6 @@ TEST_F(DcmDaemonMainInitTest, MainInit_AllComponentsInitializeSuccessfully_Succe EXPECT_NE(dcmHandle.pDcmSetHandle, nullptr); EXPECT_NE(dcmHandle.pRbusHandle, nullptr); EXPECT_NE(dcmHandle.pExecBuff, nullptr); - EXPECT_NE(dcmHandle.pLogSchedHandle, nullptr); EXPECT_NE(dcmHandle.pDifdSchedHandle, nullptr); } @@ -308,7 +304,6 @@ class DcmDaemonMainUnInitTest : public ::testing::Test { } if (dcmSchedInit() == DCM_SUCCESS) { - testHandle.pLogSchedHandle = dcmSchedAddJob("test_log", nullptr, nullptr); testHandle.pDifdSchedHandle = dcmSchedAddJob("test_difd", nullptr, nullptr); } @@ -318,7 +313,7 @@ class DcmDaemonMainUnInitTest : public ::testing::Test { } void cleanupTestComponents() { - if (testHandle.pLogSchedHandle || testHandle.pDifdSchedHandle) { + if (testHandle.pDifdSchedHandle) { dcmSchedUnInit(); } } @@ -347,7 +342,6 @@ TEST_F(DcmDaemonMainUnInitTest, UnInit_ValidHandle_CompletesSuccessfully) { EXPECT_EQ(testHandle.pExecBuff, nullptr); EXPECT_EQ(testHandle.pDcmSetHandle, nullptr); EXPECT_EQ(testHandle.pRbusHandle, nullptr); - EXPECT_EQ(testHandle.pLogSchedHandle, nullptr); EXPECT_EQ(testHandle.pDifdSchedHandle, nullptr); } From 23e2a4a1d9ede59373ac03e82883d213ab13324e Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 15:59:45 +0530 Subject: [PATCH 095/108] Update backup_logs.c --- backup_logs/src/backup_logs.c | 1 - 1 file changed, 1 deletion(-) diff --git a/backup_logs/src/backup_logs.c b/backup_logs/src/backup_logs.c index 601882da..187493d7 100644 --- a/backup_logs/src/backup_logs.c +++ b/backup_logs/src/backup_logs.c @@ -296,7 +296,6 @@ int backup_logs_main(int argc, char *argv[]) { return EXIT_FAILURE; } - /* Cleanup and exit */ RDK_LOG(RDK_LOG_DEBUG, LOG_BACKUP_LOGS, "Starting cleanup and shutdown\n"); result = backup_logs_cleanup(&config); From 07dd99d5609d23097163aa24f08f63df5118ac6f Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:01:01 +0530 Subject: [PATCH 096/108] Update backup_logs.c --- backup_logs/src/backup_logs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backup_logs/src/backup_logs.c b/backup_logs/src/backup_logs.c index 187493d7..193ae1c6 100644 --- a/backup_logs/src/backup_logs.c +++ b/backup_logs/src/backup_logs.c @@ -35,7 +35,6 @@ #include #include #include -#include #define BACKUP_LOGS_VERSION "1.0.0" #define BACKUP_LOGS_BUILD_DATE __DATE__ @@ -287,7 +286,7 @@ int backup_logs_main(int argc, char *argv[]) { return EXIT_FAILURE; } - /* Execute backup process */ + /* Execute backup process */ RDK_LOG(RDK_LOG_INFO, LOG_BACKUP_LOGS, "Starting backup execution\n"); result = backup_logs_execute(&config); if (result != BACKUP_SUCCESS) { From b098228a98d9f014c6efe58b9c240097e28e63df Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:03:01 +0530 Subject: [PATCH 097/108] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- uploadstblogs/include/uploadstblogs_types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 6e34c52e..8a745630 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -406,7 +406,6 @@ time_t apply_ntp_fallback_time(void); void trigger_reboot_info_update(void); int wait_for_sentinel(const char *flag_path, const char *watch_dir, const char *filename, unsigned int timeout_s); int wait_for_reboot_reason(void); -int wait_for_ntp_sync(void); int wait_for_telemetry_prevlogs_done(void); #endif /* UPLOADSTBLOGS_TYPES_H */ From ecbd48b096821eb87d650056dba33fb3bb9b75ea Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:05:13 +0530 Subject: [PATCH 098/108] Update context_manager.c --- uploadstblogs/src/context_manager.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/uploadstblogs/src/context_manager.c b/uploadstblogs/src/context_manager.c index a62e3c34..a713ed2e 100755 --- a/uploadstblogs/src/context_manager.c +++ b/uploadstblogs/src/context_manager.c @@ -156,24 +156,12 @@ bool init_context(RuntimeContext* ctx) { // Initialize RDK Logger /* Extended initialization with programmatic configuration */ - //RDK Logger Initialisation - /* - rdk_LogOutput_File filelog; - strncpy(filelog.fileName, "logupload.log", sizeof(filelog.fileName)-1); - filelog.fileName[sizeof(filelog.fileName) - 1] = '\0'; - strncpy(filelog.fileLocation, "/opt/logs/", sizeof(filelog.fileLocation)-1); - filelog.fileLocation[sizeof(filelog.fileLocation) - 1] = '\0'; - filelog.fileSizeMax = 10240; - filelog.fileCountMax = 1; */ - rdk_logger_ext_config_t config = { .pModuleName = "LOG.RDK.UPLOADSTB", /* Module name */ .loglevel = RDK_LOG_INFO, /* Default log level */ - //.output = RDKLOG_OUTPUT_FILE, /* Output to console (stdout/stderr) */ - .output = RDKLOG_OUTPUT_CONSOLE, + .output = RDKLOG_OUTPUT_CONSOLE, /* Output to console (stdout/stderr) */ .format = RDKLOG_FORMAT_WITH_TS, /* Timestamped format */ - //.pFilePolicy = &filelog /* Not using file output, so NULL */ - .pFilePolicy = NULL + .pFilePolicy = NULL /* Not using file output, so NULL */ }; if (rdk_logger_ext_init(&config) != RDK_SUCCESS) { From 4065605696db4b33bf681685a70ac23a30f34d1a Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:07:32 +0530 Subject: [PATCH 099/108] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- uploadstblogs/src/strategies.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index efd8ca39..f3f03805 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -74,8 +74,14 @@ size_t internet_write_cb(void *ptr, size_t size, size_t nmemb, void *userp) { rpc_resp_t *r = (rpc_resp_t *)userp; size_t incoming = size * nmemb; - size_t space = sizeof(r->buf) - r->len - 1u; + + if (r->len >= (sizeof(r->buf) - 1u)) { + return size * nmemb; /* discard extra data but keep curl happy */ + } + + size_t space = (sizeof(r->buf) - 1u) - r->len; if (incoming > space) { incoming = space; } + memcpy(r->buf + r->len, ptr, incoming); r->len += incoming; r->buf[r->len] = '\0'; From d1e12e853d1aa6a1bbd61cff4496531981c0a3bb Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:15:40 +0530 Subject: [PATCH 100/108] Update archive_manager_gtest.cpp --- .../unittest/archive_manager_gtest.cpp | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/uploadstblogs/unittest/archive_manager_gtest.cpp b/uploadstblogs/unittest/archive_manager_gtest.cpp index dab9fa20..d30e746c 100755 --- a/uploadstblogs/unittest/archive_manager_gtest.cpp +++ b/uploadstblogs/unittest/archive_manager_gtest.cpp @@ -22,6 +22,11 @@ #include #include #include +#include + +#define GTEST_DEFAULT_RESULT_FILEPATH "/tmp/Gtest_Report/" +#define GTEST_DEFAULT_RESULT_FILENAME "archive_manager_gtest_report.json" +#define GTEST_REPORT_FILEPATH_SIZE 256 // Mock RDK_LOG before including other headers #ifdef GTEST_ENABLE @@ -83,10 +88,16 @@ static int g_fread_call_count = 0; // Global counter for fread calls per file // Helper function to detect if this is a test-related file we should mock // Mock implementations FILE* fopen(const char* filename, const char* mode) { - // Don't mock system library files - return nullptr to prevent crashes - if (!filename || strstr(filename, "log4c") || strstr(filename, "rdk_debug") || - strstr(filename, "/etc/") || strstr(filename, "/usr/")) { - return nullptr; + if (!filename) return nullptr; + // Delegate to real fopen for system files and GTest output files to prevent + // crashes when GTest writes its JSON report using the fake mock FILE pointer. + if (strstr(filename, "log4c") || strstr(filename, "rdk_debug") || + strstr(filename, "/etc/") || strstr(filename, "/usr/") || + strstr(filename, GTEST_DEFAULT_RESULT_FILEPATH) || strstr(filename, ".json")) { + typedef FILE* (*real_fopen_t)(const char*, const char*); + static real_fopen_t real_fopen = nullptr; + if (!real_fopen) real_fopen = (real_fopen_t)dlsym(RTLD_NEXT, "fopen"); + return real_fopen ? real_fopen(filename, mode) : nullptr; } if (strstr(filename, "fail")) return nullptr; g_fread_call_count = 0; @@ -98,7 +109,11 @@ int fclose(FILE* stream) { g_fread_call_count = 0; return 0; } - return -1; + // Delegate to real fclose for real FILE handles (e.g., GTest output files) + typedef int (*real_fclose_t)(FILE*); + static real_fclose_t real_fclose = nullptr; + if (!real_fclose) real_fclose = (real_fclose_t)dlsym(RTLD_NEXT, "fclose"); + return (real_fclose && stream) ? real_fclose(stream) : -1; } size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { @@ -116,8 +131,14 @@ size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { } size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) { - if (stream != mock_file_ptr || !ptr) return 0; - return nmemb; + if (stream == mock_file_ptr) { + return ptr ? nmemb : 0; + } + // Delegate to real fwrite for real FILE handles (e.g., gcov .gcda profiling output) + typedef size_t (*real_fwrite_t)(const void*, size_t, size_t, FILE*); + static real_fwrite_t real_fwrite = nullptr; + if (!real_fwrite) real_fwrite = (real_fwrite_t)dlsym(RTLD_NEXT, "fwrite"); + return (real_fwrite && ptr && stream) ? real_fwrite(ptr, size, nmemb, stream) : 0; } int stat(const char* path, struct stat* buf) { @@ -671,15 +692,17 @@ TEST_F(ArchiveManagerTest, CollectDriLogs_Success) { EXPECT_GE(result, 0); } -int main(int argc, char** argv) { +GTEST_API_ int main(int argc, char *argv[]){ + char testresults_fullfilepath[GTEST_REPORT_FILEPATH_SIZE]; + char buffer[GTEST_REPORT_FILEPATH_SIZE]; + + memset( testresults_fullfilepath, 0, GTEST_REPORT_FILEPATH_SIZE ); + memset( buffer, 0, GTEST_REPORT_FILEPATH_SIZE ); + + snprintf( testresults_fullfilepath, GTEST_REPORT_FILEPATH_SIZE, "json:%s%s" , GTEST_DEFAULT_RESULT_FILEPATH , GTEST_DEFAULT_RESULT_FILENAME); + ::testing::GTEST_FLAG(output) = testresults_fullfilepath; ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); - - // Ensure global mock is cleaned up - if (g_mockFileOperations) { - delete g_mockFileOperations; - g_mockFileOperations = nullptr; - } - - return result; + //testing::Mock::AllowLeak(mock); + return RUN_ALL_TESTS(); } + From c4eceb3f48c0df4d3905fe371a51f7173286745b Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:20:14 +0530 Subject: [PATCH 101/108] Delete logupload.service --- logupload.service | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 logupload.service diff --git a/logupload.service b/logupload.service deleted file mode 100644 index 6cb5599e..00000000 --- a/logupload.service +++ /dev/null @@ -1,32 +0,0 @@ -########################################################################## -# If not stated otherwise in this file or this component's LICENSE -# file the following copyright and licenses apply: -# -# Copyright 2024 Comcast Cable Communications Management, LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -########################################################################## - -[Unit] -Description=To start Logupload -After= rbus.service iarmbusd.service network-online.target tr69hostif.service - -[Service] -Type=simple -RemainAfterExit=No -ExecStart=/usr/bin/logupload - -[Install] -WantedBy=multi-user.target From e93bf038864589426c095588dfbd72906661a436 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 16:33:10 +0530 Subject: [PATCH 102/108] Update dcm_gtest.cpp --- unittest/dcm_gtest.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/unittest/dcm_gtest.cpp b/unittest/dcm_gtest.cpp index 1ab473b4..89122358 100644 --- a/unittest/dcm_gtest.cpp +++ b/unittest/dcm_gtest.cpp @@ -251,11 +251,6 @@ class DcmRunJobsTest : public ::testing::Test { const char* originalPath; }; -TEST_F(DcmRunJobsTest, RunJobs_LogUploadProfile_ExecutesCorrectScript) { - setenv("DCM_RDK_PATH", "/tmp/test_dcm_scripts", 1); - EXPECT_NO_THROW(get_dcmRunJobs(DCM_LOGUPLOAD_SCHED, &dcmHandle)); -} - TEST_F(DcmRunJobsTest, RunJobs_DifdProfile_ExecutesCorrectScript) { setenv("DCM_RDK_PATH", "/tmp/test_dcm_scripts", 1); EXPECT_NO_THROW(get_dcmRunJobs(DCM_DIFD_SCHED, &dcmHandle)); From 95572430d31b571cd51b937ef5c4bbf873de312a Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 17:11:35 +0530 Subject: [PATCH 103/108] Update strategies_gtest.cpp --- uploadstblogs/unittest/strategies_gtest.cpp | 190 +++++++++++++++++++- 1 file changed, 189 insertions(+), 1 deletion(-) diff --git a/uploadstblogs/unittest/strategies_gtest.cpp b/uploadstblogs/unittest/strategies_gtest.cpp index 9c724674..159a38d3 100755 --- a/uploadstblogs/unittest/strategies_gtest.cpp +++ b/uploadstblogs/unittest/strategies_gtest.cpp @@ -1089,7 +1089,7 @@ TEST_F(HelperFunctionsTest, NmQueryIpver_IPv6_NoThunder) { /** * @test apply_ntp_fallback_time returns 0 when clock file is unreadable. - * Covers: fopen returns NULL path (mocked fopen returns nullptr when g_mock_file_ops is NULL). + * Covers: fopen returns NULL → early return 0. */ TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_FileNotReadable) { // With g_mock_file_ops = nullptr, fopen always returns nullptr @@ -1097,6 +1097,194 @@ TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_FileNotReadable) { EXPECT_EQ(result, 0); } +/** + * @test apply_ntp_fallback_time returns 0 when clock file is empty. + * Covers: fopen succeeds, fgets returns NULL → fclose + return 0. + */ +TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_EmptyFile) { + // Create an empty temp file + char temp_file[64]; + snprintf(temp_file, sizeof(temp_file), "/tmp/ntp_test_empty_%d", getpid()); + int fd = open(temp_file, O_CREAT | O_WRONLY | O_TRUNC, 0644); + ASSERT_GE(fd, 0); + close(fd); + + // Open for reading via fdopen (NOT mocked) to get a valid FILE* + fd = open(temp_file, O_RDONLY); + ASSERT_GE(fd, 0); + FILE* real_fp = fdopen(fd, "r"); + ASSERT_NE(nullptr, real_fp); + + // Temporarily set mock to return our real FILE* + MockFileOperations mock_ops; + g_mock_file_ops = &mock_ops; + EXPECT_CALL(mock_ops, fopen(_, _)).WillOnce(Return(real_fp)); + EXPECT_CALL(mock_ops, fclose(_)).WillOnce(Return(0)); + + time_t result = apply_ntp_fallback_time(); + EXPECT_EQ(result, 0); + + g_mock_file_ops = nullptr; + // Close the real fd (mocked fclose didn't actually close it) + fclose(real_fp); + unlink(temp_file); +} + +/** + * @test apply_ntp_fallback_time returns 0 when file contains invalid epoch (non-numeric). + * Covers: fopen succeeds, fgets succeeds, strtol returns 0 → return 0. + */ +TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_InvalidEpochString) { + char temp_file[64]; + snprintf(temp_file, sizeof(temp_file), "/tmp/ntp_test_invalid_%d", getpid()); + int fd = open(temp_file, O_CREAT | O_WRONLY | O_TRUNC, 0644); + ASSERT_GE(fd, 0); + const char* content = "not_a_number\n"; + write(fd, content, strlen(content)); + close(fd); + + fd = open(temp_file, O_RDONLY); + ASSERT_GE(fd, 0); + FILE* real_fp = fdopen(fd, "r"); + ASSERT_NE(nullptr, real_fp); + + MockFileOperations mock_ops; + g_mock_file_ops = &mock_ops; + EXPECT_CALL(mock_ops, fopen(_, _)).WillOnce(Return(real_fp)); + EXPECT_CALL(mock_ops, fclose(_)).WillOnce(Return(0)); + + time_t result = apply_ntp_fallback_time(); + EXPECT_EQ(result, 0); + + g_mock_file_ops = nullptr; + fclose(real_fp); + unlink(temp_file); +} + +/** + * @test apply_ntp_fallback_time returns 0 when file contains negative epoch. + * Covers: fopen succeeds, fgets succeeds, strtol returns < 0 → return 0. + */ +TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_NegativeEpoch) { + char temp_file[64]; + snprintf(temp_file, sizeof(temp_file), "/tmp/ntp_test_neg_%d", getpid()); + int fd = open(temp_file, O_CREAT | O_WRONLY | O_TRUNC, 0644); + ASSERT_GE(fd, 0); + const char* content = "-100\n"; + write(fd, content, strlen(content)); + close(fd); + + fd = open(temp_file, O_RDONLY); + ASSERT_GE(fd, 0); + FILE* real_fp = fdopen(fd, "r"); + ASSERT_NE(nullptr, real_fp); + + MockFileOperations mock_ops; + g_mock_file_ops = &mock_ops; + EXPECT_CALL(mock_ops, fopen(_, _)).WillOnce(Return(real_fp)); + EXPECT_CALL(mock_ops, fclose(_)).WillOnce(Return(0)); + + time_t result = apply_ntp_fallback_time(); + EXPECT_EQ(result, 0); + + g_mock_file_ops = nullptr; + fclose(real_fp); + unlink(temp_file); +} + +/** + * @test apply_ntp_fallback_time returns 0 when file contains zero. + * Covers: fopen succeeds, fgets succeeds, strtol returns 0 (epoch <= 0) → return 0. + */ +TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_ZeroEpoch) { + char temp_file[64]; + snprintf(temp_file, sizeof(temp_file), "/tmp/ntp_test_zero_%d", getpid()); + int fd = open(temp_file, O_CREAT | O_WRONLY | O_TRUNC, 0644); + ASSERT_GE(fd, 0); + const char* content = "0\n"; + write(fd, content, strlen(content)); + close(fd); + + fd = open(temp_file, O_RDONLY); + ASSERT_GE(fd, 0); + FILE* real_fp = fdopen(fd, "r"); + ASSERT_NE(nullptr, real_fp); + + MockFileOperations mock_ops; + g_mock_file_ops = &mock_ops; + EXPECT_CALL(mock_ops, fopen(_, _)).WillOnce(Return(real_fp)); + EXPECT_CALL(mock_ops, fclose(_)).WillOnce(Return(0)); + + time_t result = apply_ntp_fallback_time(); + EXPECT_EQ(result, 0); + + g_mock_file_ops = nullptr; + fclose(real_fp); + unlink(temp_file); +} + +/** + * @test apply_ntp_fallback_time returns valid epoch on success. + * Covers: fopen succeeds, fgets succeeds, strtol returns > 0 → return epoch. + */ +TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_ValidEpoch) { + char temp_file[64]; + snprintf(temp_file, sizeof(temp_file), "/tmp/ntp_test_valid_%d", getpid()); + int fd = open(temp_file, O_CREAT | O_WRONLY | O_TRUNC, 0644); + ASSERT_GE(fd, 0); + const char* content = "1700000000\n"; + write(fd, content, strlen(content)); + close(fd); + + fd = open(temp_file, O_RDONLY); + ASSERT_GE(fd, 0); + FILE* real_fp = fdopen(fd, "r"); + ASSERT_NE(nullptr, real_fp); + + MockFileOperations mock_ops; + g_mock_file_ops = &mock_ops; + EXPECT_CALL(mock_ops, fopen(_, _)).WillOnce(Return(real_fp)); + EXPECT_CALL(mock_ops, fclose(_)).WillOnce(Return(0)); + + time_t result = apply_ntp_fallback_time(); + EXPECT_EQ(result, (time_t)1700000000); + + g_mock_file_ops = nullptr; + fclose(real_fp); + unlink(temp_file); +} + +/** + * @test apply_ntp_fallback_time handles epoch with leading whitespace. + * Covers: strtol skips leading whitespace per C standard → returns valid epoch. + */ +TEST_F(HelperFunctionsTest, ApplyNtpFallbackTime_EpochWithWhitespace) { + char temp_file[64]; + snprintf(temp_file, sizeof(temp_file), "/tmp/ntp_test_ws_%d", getpid()); + int fd = open(temp_file, O_CREAT | O_WRONLY | O_TRUNC, 0644); + ASSERT_GE(fd, 0); + const char* content = " 1642780800\n"; + write(fd, content, strlen(content)); + close(fd); + + fd = open(temp_file, O_RDONLY); + ASSERT_GE(fd, 0); + FILE* real_fp = fdopen(fd, "r"); + ASSERT_NE(nullptr, real_fp); + + MockFileOperations mock_ops; + g_mock_file_ops = &mock_ops; + EXPECT_CALL(mock_ops, fopen(_, _)).WillOnce(Return(real_fp)); + EXPECT_CALL(mock_ops, fclose(_)).WillOnce(Return(0)); + + time_t result = apply_ntp_fallback_time(); + EXPECT_EQ(result, (time_t)1642780800); + + g_mock_file_ops = nullptr; + fclose(real_fp); + unlink(temp_file); +} + // ---- trigger_reboot_info_update tests ---- /** From ff2903e65aa14855559dff7888b249fc2e4b4224 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Mon, 13 Jul 2026 17:12:09 +0530 Subject: [PATCH 104/108] Update dcm.h --- dcm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/dcm.h b/dcm.h index 3d157849..bdefc16f 100644 --- a/dcm.h +++ b/dcm.h @@ -26,7 +26,6 @@ extern "C" { #endif - #define DCM_DIFD_SCHED "DCM_FW_UPDATE" typedef struct _dcmdHandle From 770e6cf5b4d5884644bfc173cf17175fd4d545dc Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 14 Jul 2026 15:40:23 +0530 Subject: [PATCH 105/108] Update strategies.c --- uploadstblogs/src/strategies.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index f3f03805..3a96fd69 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -228,7 +228,6 @@ void trigger_reboot_info_update(void) * 3. Re-check after watch is established to close the creation race window. * 4. select() loop with 2 s heartbeat; exit when sentinel appears or * timeout_s total seconds have elapsed. - * 5. Fallback: if inotify_init1 or inotify_add_watch fails, poll with 1 s sleep. * * Returns 0 when the sentinel is detected within the timeout. * Returns -1 on timeout or inotify fallback timeout. @@ -253,6 +252,7 @@ int wait_for_sentinel(const char *flag_path, const char *watch_dir, const char * "[%s:%d] inotify_add_watch on %s failed (errno=%d); falling back to polling for %s\n", __FUNCTION__, __LINE__, watch_dir, errno, flag_path); close(ifd); + return -1; } /* Re-check after watch is set — closes race between access() and add_watch */ @@ -266,10 +266,11 @@ int wait_for_sentinel(const char *flag_path, const char *watch_dir, const char * struct timespec deadline; if (clock_gettime(CLOCK_MONOTONIC, &deadline) != 0) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, - "[%s:%d] clock_gettime failed (errno=%d); falling back to polling for %s\n", - __FUNCTION__, __LINE__, errno, flag_path); + "[%s:%d] clock_gettime failed (errno=%d) \n", + __FUNCTION__, __LINE__, errno); inotify_rm_watch(ifd, wd); close(ifd); + return -1 } deadline.tv_sec += (time_t)timeout_s; From 44a2cdad9e9a2911efffb9f501206d31c129d265 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:43:44 +0530 Subject: [PATCH 106/108] Update strategies.c --- uploadstblogs/src/strategies.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 3a96fd69..1f5b5281 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -208,7 +208,7 @@ void trigger_reboot_info_update(void) if (fd >= 0) { close(fd); RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, - "[%s:%d] Touched STT_FLAG to trigger reboot reason update: %s\n", + "[%s:%d] Trigger reboot reason update: %s\n", __FUNCTION__, __LINE__, STT_FLAG); } } From 93b72bbc9e48d09bb625c4f90701816ff20fe25f Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:38:47 +0530 Subject: [PATCH 107/108] Update strategies.c --- uploadstblogs/src/strategies.c | 58 +--------------------------------- 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/uploadstblogs/src/strategies.c b/uploadstblogs/src/strategies.c index 1f5b5281..b5f210ce 100644 --- a/uploadstblogs/src/strategies.c +++ b/uploadstblogs/src/strategies.c @@ -140,17 +140,6 @@ bool check_internet_connectivity(void) return nm_query_ipver("IPv6"); } - -/** - * apply_ntp_fallback_time - Read last-known-good epoch from systimemgr clock file. - * - * Called when STT_FLAG is absent but internet connectivity is available. - * Returns the epoch seconds read from SYSTIMEMGR_CLOCK_FILE so the caller can - * embed it directly in the archive filename via ctx->archive_ref_time. - * Does NOT modify the system clock. - * - * Returns the epoch (> 0) on success, 0 on any failure. - */ time_t apply_ntp_fallback_time(void) { char time_buf[32] = {0}; @@ -187,18 +176,6 @@ time_t apply_ntp_fallback_time(void) return (time_t)epoch; } -/* ---- Prerequisite sentinel helpers ---- */ - -/** - * trigger_reboot_info_update - Touch STT_FLAG to trigger reboot-reason update. - * - * Called only after wait_for_reboot_reason() times out. - * Touching STT_FLAG (/tmp/stt_received) signals update-prev-reboot-info - * (reboot-manager) to perform an immediate reboot-reason update; reboot-manager - * watches STT_FLAG as its primary gate to run update_reboot_info(). - * - * Cross-repo interface: STT_FLAG is watched by reboot-manager. - */ void trigger_reboot_info_update(void) { struct stat st; @@ -214,24 +191,6 @@ void trigger_reboot_info_update(void) } } -/** - * wait_for_sentinel - Generic inotify-based wait for a sentinel file. - * - * @param flag_path Full path to the sentinel file (e.g. "/tmp/.backup_logs_done") - * @param watch_dir Directory to watch (e.g. "/tmp") - * @param filename Basename of the sentinel (e.g. ".backup_logs_done") - * @param timeout_s Maximum wait in seconds (CLOCK_MONOTONIC) - * - * Strategy: - * 1. Fast path: sentinel already present → return 0 immediately. - * 2. Set up inotify on watch_dir for IN_CREATE | IN_MOVED_TO. - * 3. Re-check after watch is established to close the creation race window. - * 4. select() loop with 2 s heartbeat; exit when sentinel appears or - * timeout_s total seconds have elapsed. - * - * Returns 0 when the sentinel is detected within the timeout. - * Returns -1 on timeout or inotify fallback timeout. - */ int wait_for_sentinel(const char *flag_path, const char *watch_dir, const char *filename, unsigned int timeout_s) { /* Fast path: sentinel already present */ @@ -327,19 +286,6 @@ int wait_for_telemetry_prevlogs_done(void) return wait_for_sentinel(TELEMETRY_PREVLOGS_DONE_FLAG, TELEMETRY_PREVLOGS_DONE_DIR, TELEMETRY_PREVLOGS_DONE_FILENAME, TELEMETRY_PREVLOGS_TIMEOUT_S); } -/** - * set_upload_annotation - Record a prerequisite-failure annotation in the session. - * - * @param session Active session. - * @param annotation One of ANNOTATION_* codes defined in uploadstblogs_types.h. - */ -static void set_upload_annotation(SessionState *session, int annotation) -{ - if (session) { - session->upload_annotations |= (1 << annotation); - } -} - /** * @brief Read upload_flag from DCMSettings.conf * @return true if upload is enabled, false otherwise @@ -970,10 +916,9 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) if (wait_for_reboot_reason() != 0) { RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB, "[%s:%d] Reboot reason sentinel not present after %us. " - "Writing trigger to request immediate update.\n", + "trigger to request immediate update.\n", __FUNCTION__, __LINE__, REBOOT_POLL_TIMEOUT_S); trigger_reboot_info_update(); - set_upload_annotation(session, ANNOTATION_REBOOT_REASON_UNAVAILABLE); } else { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Reboot reason sentinel detected. Proceeding.\n", @@ -997,7 +942,6 @@ static int reboot_setup(RuntimeContext* ctx, SessionState* session) "[%s:%d] Telemetry prevlogs sentinel not present after %us; " "proceeding without telemetry sync\n", __FUNCTION__, __LINE__, TELEMETRY_PREVLOGS_TIMEOUT_S); - session->upload_annotations |= (1 << ANNOTATION_TELEMETRY_PREVLOGS_UNAVAILABLE); } else { RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Telemetry prevlogs sentinel detected. Proceeding.\n", From 3acbb1da9185689278f6a97adc7dc17e07a05ff0 Mon Sep 17 00:00:00 2001 From: Abhinavpv28 <162570454+Abhinavpv28@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:40:53 +0530 Subject: [PATCH 108/108] Update uploadstblogs_types.h --- uploadstblogs/include/uploadstblogs_types.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/uploadstblogs/include/uploadstblogs_types.h b/uploadstblogs/include/uploadstblogs_types.h index 8a745630..5a7bd239 100755 --- a/uploadstblogs/include/uploadstblogs_types.h +++ b/uploadstblogs/include/uploadstblogs_types.h @@ -84,10 +84,6 @@ #endif #define REBOOT_POLL_INTERVAL_S 1u /* fallback polling interval */ -/** Annotation code set in SessionState when the reboot-reason sentinel times out. - * Upload always proceeds; this records that previousreboot.info was unavailable. */ -#define ANNOTATION_REBOOT_REASON_UNAVAILABLE 1 - /** NTP sync completion sentinel — written by systimemgr when NTP is synchronised. * Presence at upload time means the system clock is accurate; absence means the * device rebooted without receiving NTP, and an internet check + last-known-good @@ -110,14 +106,6 @@ #define TELEMETRY_PREVLOGS_TIMEOUT_S 120u #endif -/** Annotation code set in SessionState when telemetry prevlogs grep did not - * complete within the timeout. Upload always proceeds. */ -#define ANNOTATION_TELEMETRY_PREVLOGS_UNAVAILABLE 3 - -/** Annotation code set in SessionState when NTP was not synced at upload time and - * internet connectivity was absent, so the last-known-good time fallback could not - * be applied. Upload always proceeds. */ -#define ANNOTATION_NTP_UNAVAILABLE 2 /** Path to the last-known-good clock file maintained by systimemgr (RdkDefaultTimeSync). * Contains a plain epoch-seconds integer written by systimemgr on every successful @@ -371,7 +359,6 @@ typedef struct { bool used_fallback; /**< Whether fallback was used */ bool success; /**< Overall success status */ char archive_file[MAX_FILENAME_LENGTH]; /**< Generated archive filename */ - int upload_annotations; /**< Bitmask of ANNOTATION_* codes set during prerequisite fallback */ } SessionState; #define THUNDER_JSONRPC_URL "http://127.0.0.1:9998/jsonrpc"