Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4647640
[support/8.5] Log-backup generated is named with local timestamp ins…
Abhinavpv28 Apr 27, 2026
75c80d1
dcmagent 2.0.3v1 hotfix release
naveenkumarhanasi Apr 27, 2026
7bc1c9d
Merge branch 'hotfix/2.0.3v1' into support/2.0.3
naveenkumarhanasi Apr 27, 2026
9bfb8e5
Add log (#121)
Abhinavpv28 Apr 29, 2026
92736b7
RDKEMW-17725 : [support/8.5] [RDKEMW][ALPACA IT] Device not Going to …
Abhinavpv28 Apr 29, 2026
9b0a838
Revert "RDKEMW-17725 : [support/8.5] [RDKEMW][ALPACA IT] Device not G…
nhanasi Apr 29, 2026
877e615
DCM agent 2.0.3v2 hotfix release
naveenkumarhanasi Apr 29, 2026
3790d94
Merge branch 'hotfix/2.0.3v2' into support/2.0.3
naveenkumarhanasi Apr 29, 2026
391c7af
Revert "Revert "RDKEMW-17725 : [support/8.5] [RDKEMW][ALPACA IT] Devi…
nhanasi Apr 29, 2026
bf5832c
DCM Agent 2.0.3v3 hotfix release
naveenkumarhanasi Apr 29, 2026
33c5639
Changelog for 2.0.3
naveenkumarhanasi Apr 29, 2026
586b053
Merge branch 'hotfix/2.0.3v3' into support/2.0.3
naveenkumarhanasi Apr 29, 2026
67994f5
RDKEMW-18351 : [8.5.3]Log upload success logs not observed after sche…
Abhinavpv28 May 13, 2026
eba2ded
DCM Agent 2.0.3v4 hotfix release
naveenkumarhanasi May 13, 2026
9338a9b
Merge branch 'hotfix/2.0.3v4' into support/2.0.3
naveenkumarhanasi May 13, 2026
bd1e32a
[8.5] RDKEMW-19218 : Add missing Logs in Log Upload C module Logs (#…
Abhinavpv28 May 28, 2026
11d62dd
DCM agent 8.5 2.0.3v5 hotfix release
naveenkumarhanasi May 28, 2026
fd599f9
Merge branch 'hotfix/2.0.3v5' into support/2.0.3
naveenkumarhanasi May 28, 2026
131d405
RDKEMW-19237: Cleanup of stale archives and log backups to the upload…
Abhinavpv28 Jun 3, 2026
7641e95
DCM Agent 2.0.3v6 hotfix release
naveenkumarhanasi Jun 3, 2026
9ccd703
Merge branch 'hotfix/2.0.3v6' into support/2.0.3
naveenkumarhanasi Jun 3, 2026
56921e3
Update archive_manager.h
Abhinavpv28 Jul 30, 2026
1aa431e
Update archive_manager.c
Abhinavpv28 Jul 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,74 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [2.0.3v6](https://github.com/rdkcentral/dcm-agent/compare/2.1.3...2.0.3v6)

- RDKEMW-19237: Cleanup of stale archives and log backups to the uploadSTBLogs [`#134`](https://github.com/rdkcentral/dcm-agent/pull/134)
- [8.5] RDKEMW-19218 : Add missing Logs in Log Upload C module Logs [`#133`](https://github.com/rdkcentral/dcm-agent/pull/133)
- RDKEMW-18351 : [8.5.3]Log upload success logs not observed after scheduled reboot [`#129`](https://github.com/rdkcentral/dcm-agent/pull/129)
- Revert "Revert "RDKEMW-17725 : [support/8.5] [RDKEMW][ALPACA IT] Device not G…" [`#125`](https://github.com/rdkcentral/dcm-agent/pull/125)
- Revert "RDKEMW-17725 : [support/8.5] [RDKEMW][ALPACA IT] Device not Going to …" [`#124`](https://github.com/rdkcentral/dcm-agent/pull/124)
- RDKEMW-17725 : [support/8.5] [RDKEMW][ALPACA IT] Device not Going to Deepsleep. [`#123`](https://github.com/rdkcentral/dcm-agent/pull/123)
- Add log [`#121`](https://github.com/rdkcentral/dcm-agent/pull/121)
- [support/8.5] Log-backup generated is named with local timestamp instead of UTC timestamp [`#117`](https://github.com/rdkcentral/dcm-agent/pull/117)
- dcmagent 2.0.3v1 hotfix release [`75c80d1`](https://github.com/rdkcentral/dcm-agent/commit/75c80d1701dd932e8e885aa3f418ae1633d6b1eb)
- DCM agent 2.0.3v2 hotfix release [`877e615`](https://github.com/rdkcentral/dcm-agent/commit/877e615fc3d17a8eb8f1de0cdbdf4d9e053a5e32)
- DCM agent 8.5 2.0.3v5 hotfix release [`11d62dd`](https://github.com/rdkcentral/dcm-agent/commit/11d62dd0644a697a8e7a9f4985b2c0d417d982c3)

#### [2.1.3](https://github.com/rdkcentral/dcm-agent/compare/2.1.2...2.1.3)

> 18 May 2026

- RDKEMW-18510: [develop]Log upload success logs not observed after scheduled reboot [`#127`](https://github.com/rdkcentral/dcm-agent/pull/127)
- DCM Agent 2.1.3 release changelog updates [`fe80498`](https://github.com/rdkcentral/dcm-agent/commit/fe804982965fb1db55917fb9d1f91573b65e6e0c)
- Merge tag '2.1.2' into develop [`7461693`](https://github.com/rdkcentral/dcm-agent/commit/7461693af0d9c1c8fbd3fb4fd374ef8858041608)

#### [2.1.2](https://github.com/rdkcentral/dcm-agent/compare/2.1.1...2.1.2)

> 29 April 2026

- RDKEMW-17638 : [RDKEMW][ALPACA IT] Device not Going to Deepsleep. [`#122`](https://github.com/rdkcentral/dcm-agent/pull/122)
- RDKEMW-17582: [develop]UploadLogsOnUnscheduledReboot.Disable RFC state not logged / not honored in 8.5 builds after Scheduled Reboot [`#119`](https://github.com/rdkcentral/dcm-agent/pull/119)
- [RDKEMW-17616] Log-backup generated is named with local timestamp instead of UTC timestamp [`#114`](https://github.com/rdkcentral/dcm-agent/pull/114)
- RDKEMW-14842 [Logupload] Sha value need to be print in dcmscript.log for all types of logupload [`#111`](https://github.com/rdkcentral/dcm-agent/pull/111)
- DCM Agent Documentaion updated for the module [`#110`](https://github.com/rdkcentral/dcm-agent/pull/110)
- RDKEMW-17026 : Remove OEM/SOC references from the module [`#113`](https://github.com/rdkcentral/dcm-agent/pull/113)
- DCM Agent 2.1.2 release changelog updates [`00ac749`](https://github.com/rdkcentral/dcm-agent/commit/00ac749be80b9d7cbfc47e60e0dcfc11005e9886)
- Merge tag '2.1.1' into develop [`be1a984`](https://github.com/rdkcentral/dcm-agent/commit/be1a9843bd5631ee54d0c1d750e827b50e9ba848)

#### [2.1.1](https://github.com/rdkcentral/dcm-agent/compare/2.1.0...2.1.1)

> 26 March 2026

- RDK-61010,RDKEMW-13361: Replace Memcapture Report Upload Script with UploadSTB Binary [`#80`](https://github.com/rdkcentral/dcm-agent/pull/80)
- DCM Agent 2.1.1 release changelog updates [`68443e9`](https://github.com/rdkcentral/dcm-agent/commit/68443e98816b1bef98089fa6640488bd27617568)

#### [2.1.0](https://github.com/rdkcentral/dcm-agent/compare/2.0.4...2.1.0)

> 25 March 2026

- RDK-61009 : [RDKE] Port Log Backup Scripts to Source code [`#100`](https://github.com/rdkcentral/dcm-agent/pull/100)
- Add tools and skills for agentic development [`#102`](https://github.com/rdkcentral/dcm-agent/pull/102)
- Changelog updates for 2.1.0 release [`2750242`](https://github.com/rdkcentral/dcm-agent/commit/2750242f81cdd6400aa331328f46a1a80abd8f16)
- Merge tag '2.0.4' into develop [`fc29d06`](https://github.com/rdkcentral/dcm-agent/commit/fc29d06b82c73b374527cbdb8bef93eab5ccfbdb)

#### [2.0.4](https://github.com/rdkcentral/dcm-agent/compare/2.0.3...2.0.4)

> 18 March 2026

- RDK-60634 [dcm-agent] RDK Coverity Defect Resolution for Device Management [`#81`](https://github.com/rdkcentral/dcm-agent/pull/81)
- RDK-61009 : [RDKE] Port Log Backup Scripts to Source code [`#95`](https://github.com/rdkcentral/dcm-agent/pull/95)
- RDK-60497 : Port USB Log Upload Scripts to Source code [`#91`](https://github.com/rdkcentral/dcm-agent/pull/91)
- RDK-60497 : Port USB Log Upload Scripts to Source code [`#79`](https://github.com/rdkcentral/dcm-agent/pull/79)
- tr69hostif 2.0.4 release changelog updates [`10f09d2`](https://github.com/rdkcentral/dcm-agent/commit/10f09d27d7200e5f8474303bbc7689f6bf8eeefa)
- Merge tag '2.0.3' into develop [`86c4755`](https://github.com/rdkcentral/dcm-agent/commit/86c47550324d871f804446459dbb0a30814d5a2a)

#### [2.0.3](https://github.com/rdkcentral/dcm-agent/compare/2.0.2...2.0.3)

> 11 February 2026

- Update context_manager.c [`#73`](https://github.com/rdkcentral/dcm-agent/pull/73)
- DCM Agent 2.0.3 release changelog updates [`45018b7`](https://github.com/rdkcentral/dcm-agent/commit/45018b7808de12690a91b45447b372ebd4af0b11)

#### [2.0.2](https://github.com/rdkcentral/dcm-agent/compare/2.0.1...2.0.2)

Expand Down
2 changes: 1 addition & 1 deletion uploadstblogs/include/archive_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ int create_archive(RuntimeContext* ctx, SessionState* session, const char* sourc
*
* Creates tar.gz archive containing DRI logs from DRI_LOG_PATH
*/
int create_dri_archive(RuntimeContext* ctx, const char* archive_path);
int create_dri_archive(RuntimeContext* ctx, SessionState* session, const char* archive_path);

/**
* @brief Generate archive filename with MAC and timestamp
Expand Down
39 changes: 15 additions & 24 deletions uploadstblogs/src/archive_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,18 +415,20 @@ bool generate_archive_name(char* buffer, size_t buffer_size,
}

time_t now = time(NULL);
struct tm* tm_info = localtime(&now);

if (!tm_info) {
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
"[%s:%d] Failed to get local time\n", __FUNCTION__, __LINE__);

struct tm tm_utc;
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 false;
}

char timestamp[32];
// Format: MM-DD-YY-HH-MMAM/PM (matches script: date "+%m-%d-%y-%I-%M%p")
strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p", tm_info);

// 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__);
return false;
}
// Remove colons from MAC address for filename (A8:4A:63 -> A84A63)
char mac_clean[32];
const char* src = mac_address;
Expand All @@ -447,8 +449,8 @@ bool generate_archive_name(char* buffer, size_t buffer_size,
__FUNCTION__, __LINE__, buffer, mac_address, prefix);

return true;
}

}
/**
* @brief Calculate TAR checksum
*/
Expand Down Expand Up @@ -765,9 +767,9 @@ static int create_archive_with_options(RuntimeContext* ctx, SessionState* sessio
* @param archive_path Output archive file path (directory portion used)
* @return 0 on success, -1 on failure
*/
int create_dri_archive(RuntimeContext* ctx, const char* archive_path)
int create_dri_archive(RuntimeContext* ctx, SessionState* session, const char* archive_path)
{
if (!ctx || !archive_path) {
if (!ctx || !session || !archive_path) {
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
"[%s:%d] Invalid parameters\n", __FUNCTION__, __LINE__);
return -1;
Expand All @@ -786,20 +788,9 @@ int create_dri_archive(RuntimeContext* ctx, const char* archive_path)
return -1;
}

// Extract output directory from archive_path
char output_dir[MAX_PATH_LENGTH];
const char* last_slash = strrchr(archive_path, '/');
if (last_slash) {
size_t dir_len = last_slash - archive_path;
snprintf(output_dir, sizeof(output_dir), "%.*s", (int)dir_len, archive_path);
} else {
strcpy(output_dir, "/tmp");
}

RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB,
"[%s:%d] Creating DRI archive from %s to %s\n",
__FUNCTION__, __LINE__, ctx->dri_log_path, output_dir);
__FUNCTION__, __LINE__, ctx->dri_log_path, ctx->dri_log_path);

// Use the common archive creation with DRI_Logs prefix
return create_archive_with_options(ctx, NULL, ctx->dri_log_path, output_dir, "DRI_Logs");
return create_archive_with_options(ctx, session, ctx->dri_log_path, ctx->dri_log_path, "DRI_Logs");
}
70 changes: 53 additions & 17 deletions uploadstblogs/src/cleanup_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <sys/stat.h>
#include <dirent.h>
#include <regex.h>
#include <ctype.h>
#include "cleanup_handler.h"
#include "context_manager.h"
#include "event_manager.h"
Expand Down Expand Up @@ -224,36 +225,71 @@ int cleanup_old_archives(const char *log_path)
return -1;
}

int dfd = dirfd(dir);
if (dfd < 0) {
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB, "[%s:%d] dirfd() failed for: %s\n", __FUNCTION__, __LINE__, log_path);
closedir(dir);
return -1;
}

int removed_count = 0;
struct dirent *entry;
char fullpath[512];

while ((entry = readdir(dir)) != NULL) {
// Check if file ends with .tgz
size_t len = strlen(entry->d_name);
if (len < 5 || strcmp(entry->d_name + len - 4, ".tgz") != 0) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}

snprintf(fullpath, sizeof(fullpath), "%s/%s", log_path, entry->d_name);

RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB,
"[%s:%d] Removing old archive: %s\n",
__FUNCTION__, __LINE__, fullpath);

// Use unlink to remove file (more explicit than remove)
if (unlink(fullpath) == 0) {
removed_count++;
} else {
RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB,
"[%s:%d] Failed to remove: %s\n",
__FUNCTION__, __LINE__, fullpath);
struct stat st;
/* fstatat with AT_SYMLINK_NOFOLLOW on the open dir FD: check and subsequent
* unlinkat both refer to the same dir entry, eliminating the TOCTOU race. */
if (fstatat(dfd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0) {
continue;
}

if (S_ISDIR(st.st_mode)) {
/* Recurse into subdirectories (matches shell: find $LOG_PATH -name "*.tgz") */
snprintf(fullpath, sizeof(fullpath), "%s/%s", log_path, entry->d_name);
int sub_count = cleanup_old_archives(fullpath);
if (sub_count > 0) {
removed_count += sub_count;
}
} else if (S_ISREG(st.st_mode)) {
size_t len = strlen(entry->d_name);
if (len < 5 || strcmp(entry->d_name + len - 4, ".tgz") != 0) {
continue;
}

int path_written = snprintf(fullpath, sizeof(fullpath), "%s/%s", log_path, entry->d_name);

if (path_written < 0 || path_written >= (int)sizeof(fullpath)) {

RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB,

"[%s:%d] Path too long, skipping file: %s/%s\n",

__FUNCTION__, __LINE__, log_path, entry->d_name);

continue;

}

RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB, "[%s:%d] Removing old archive: %s\n", __FUNCTION__, __LINE__, fullpath);
/* unlinkat operates on the same dir FD — no path race possible */
if (unlinkat(dfd, entry->d_name, 0) == 0) {
removed_count++;
} else {
RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB,
"[%s:%d] Failed to remove: %s\n",
__FUNCTION__, __LINE__, fullpath);
}
}
}

closedir(dir);

RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB,
RDK_LOG(RDK_LOG_DEBUG, LOG_UPLOADSTB,
"[%s:%d] Archive cleanup complete: removed %d .tgz files from %s\n",
__FUNCTION__, __LINE__, removed_count, log_path);

Expand Down
10 changes: 4 additions & 6 deletions uploadstblogs/src/event_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,9 @@ void emit_upload_failure(const RuntimeContext* ctx, const SessionState* session)
void emit_upload_aborted(void)
{
RDK_LOG(RDK_LOG_WARN, LOG_UPLOADSTB,
"[%s:%d] Upload operation was aborted\n", __FUNCTION__, __LINE__);
"[%s:%d] Not Uploading Logs with DCM \n", __FUNCTION__, __LINE__);

// Send abort events
send_iarm_event("LogUploadEvent", LOG_UPLOAD_ABORTED);
send_iarm_event("LogUploadEvent", LOG_UPLOAD_FAILED);
send_iarm_event_maintenance(MAINT_LOGUPLOAD_ERROR);
}

Expand Down Expand Up @@ -432,7 +431,6 @@ 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 error event (matches script behavior)
send_iarm_event_maintenance(MAINT_LOGUPLOAD_ERROR);
// Send maintenance complete event (matches script behavior)
send_iarm_event_maintenance(MAINT_LOGUPLOAD_COMPLETE);
}

29 changes: 22 additions & 7 deletions uploadstblogs/src/file_operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,13 +348,26 @@ int add_timestamp_to_files(const char* dir_path)

// Get current timestamp in script format: MM-DD-YY-HH-MMAM/PM-
time_t now = time(NULL);
struct tm* tm_info = localtime(&now);
struct tm tm_utc;
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;
}
char timestamp[32];
strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-", tm_info);

size_t timestamp_len = strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-", &tm_utc);
if (timestamp_len == 0) {
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
"[%s:%d] Failed to format UTC timestamp\n",
__FUNCTION__, __LINE__);
return -1;
}

// Store timestamp prefix globally for removal later (matches script behavior)

strncpy(g_timestamp_prefix, timestamp, sizeof(g_timestamp_prefix) - 1);

g_timestamp_prefix[sizeof(g_timestamp_prefix) - 1] = '\0';

DIR* dir = opendir(dir_path);
if (!dir) {
RDK_LOG(RDK_LOG_ERROR, LOG_UPLOADSTB,
Expand Down Expand Up @@ -412,7 +425,6 @@ int add_timestamp_to_files(const char* dir_path)

return (error_count > 0) ? -1 : 0;
}

/**
* @brief Remove timestamp prefix from all files in directory
* @param dir_path Directory containing files to rename
Expand Down Expand Up @@ -538,9 +550,13 @@ int add_timestamp_to_files_uploadlogsnow(const char* dir_path)

// Get current timestamp in script format: MM-DD-YY-HH-MMAM/PM-
time_t now = time(NULL);
struct tm* tm_info = localtime(&now);
struct tm tm_utc;
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;
}
char timestamp[32];
strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-", tm_info);
strftime(timestamp, sizeof(timestamp), "%m-%d-%y-%I-%M%p-", &tm_utc);

// Store timestamp prefix globally for removal later (matches script behavior)
strncpy(g_timestamp_prefix, timestamp, sizeof(g_timestamp_prefix) - 1);
Expand Down Expand Up @@ -641,7 +657,6 @@ int add_timestamp_to_files_uploadlogsnow(const char* dir_path)

return (error_count > 0) ? -1 : 0;
}

/**
* @brief Move all contents from source directory to destination directory
* @param src_dir Source directory
Expand Down
1 change: 1 addition & 0 deletions uploadstblogs/src/path_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ static UploadResult perform_s3_put_with_fallback(RuntimeContext* ctx, SessionSta
if (s3_verified == UPLOADSTB_SUCCESS) {
t2_count_notify("TEST_lu_success"); // Script line 616
session->success = true;
RDK_LOG(RDK_LOG_INFO, LOG_UPLOADSTB, "[%s:%d] Direct log upload Success: httpcode= %d\n", __FUNCTION__, __LINE__, session->http_code);
return UPLOADSTB_SUCCESS;
}

Expand Down
Loading