Skip to content

Commit

Permalink
Add ECUSoftwareVersionFileField option to dlt.conf (#554)
Browse files Browse the repository at this point in the history
Modify dlt_daemon_local_ecu_version_init() to read a single field from
KEY=VALUE (or quoted KEY="VALUE") style files, so that dlt-daemon can
report an OS version number parsed from /etc/os-release file.

For example, get_software_version would return "22.04.3 LTS" under the
following configuration:

$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION="22.04.3 LTS"
VERSION_CODENAME=jammy

$ cat /etc/dlt.conf
PathToECUSoftwareVersion = /etc/os-release
ECUSoftwareVersionFileField = VERSION

Signed-off-by: Haris Okanovic <[email protected]>
Co-authored-by: Haris Okanovic <[email protected]>
  • Loading branch information
harisokanovic and Haris Okanovic authored Nov 14, 2023
1 parent 6b2e57b commit 7a55368
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 50 deletions.
173 changes: 123 additions & 50 deletions src/daemon/dlt-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ int option_file_parser(DltDaemonLocal *daemon_local)
daemon_local->daemonFifoSize = 0;
daemon_local->flags.sendECUSoftwareVersion = 0;
memset(daemon_local->flags.pathToECUSoftwareVersion, 0, sizeof(daemon_local->flags.pathToECUSoftwareVersion));
memset(daemon_local->flags.ecuSoftwareVersionFileField, 0, sizeof(daemon_local->flags.ecuSoftwareVersionFileField));
daemon_local->flags.sendTimezone = 0;
daemon_local->flags.offlineLogstorageMaxDevices = 0;
daemon_local->flags.offlineLogstorageDirPath[0] = 0;
Expand Down Expand Up @@ -632,6 +633,13 @@ int option_file_parser(DltDaemonLocal *daemon_local)
- 1] = 0;
/*printf("Option: %s=%s\n",token,value); */
}
else if (strcmp(token, "ECUSoftwareVersionFileField") == 0) {
strncpy(daemon_local->flags.ecuSoftwareVersionFileField, value,
sizeof(daemon_local->flags.ecuSoftwareVersionFileField) - 1);
daemon_local->flags.ecuSoftwareVersionFileField[sizeof(daemon_local->flags.ecuSoftwareVersionFileField)
- 1] = 0;
/*printf("Option: %s=%s\n",token,value); */
}
else if (strcmp(token, "SendTimezone") == 0)
{
daemon_local->flags.sendTimezone = atoi(value);
Expand Down Expand Up @@ -1906,78 +1914,143 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon,
return 0;
}

int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
static char* file_read_everything(FILE* const file, const size_t sizeLimit)
{
char *version = NULL;
FILE *f = NULL;

PRINT_FUNCTION_VERBOSE(verbose);

/* By default, version string is null. */
daemon->ECUVersionString = NULL;

/* Open the file. Bail out if error occurs */
f = fopen(daemon_local->flags.pathToECUSoftwareVersion, "r");

if (f == NULL) {
/* Error level notice, because this might be deliberate choice */
dlt_log(LOG_NOTICE, "Failed to open ECU Software version file.\n");
return -1;
if (!file) {
return NULL;
}

/* Get the file size. Bail out if stat fails. */
int fd = fileno(f);
struct stat s_buf;

const int fd = fileno(file);
struct stat s_buf = {0};
if (fstat(fd, &s_buf) < 0) {
dlt_log(LOG_WARNING, "Failed to stat ECU Software version file.\n");
fclose(f);
dlt_log(LOG_WARNING, "failed to stat file size\n");
fclose(file);
return -1;
}

/* Bail out if file is too large. Use DLT_DAEMON_TEXTBUFSIZE max.
* Reserve one byte for trailing '\0' */
off_t size = s_buf.st_size;
/* Size limit includes NULL terminator. */
const off_t size = s_buf.st_size;
if (size < 0 || size >= sizeLimit) {
dlt_log(LOG_WARNING, "file size invalid\n");
fclose(file);
return NULL;
}

if (size >= DLT_DAEMON_TEXTBUFSIZE) {
dlt_log(LOG_WARNING, "Too large file for ECU version.\n");
fclose(f);
return -1;
char* const string = malloc((size_t)size + 1);
if (!string) {
dlt_log(LOG_WARNING, "failed to allocate string for file contents\n");
fclose(file);
return NULL;
}

/* Allocate permanent buffer for version info */
version = malloc((size_t) (size + 1));
off_t offset = 0;
while (!feof(file)) {
offset += (off_t)fread(string + offset, 1, (size_t)size, file);

if (version == 0) {
dlt_log(LOG_WARNING, "Cannot allocate memory for ECU version.\n");
fclose(f);
return -1;
if (ferror(file)) {
dlt_log(LOG_WARNING, "failed to read file\n");
free(string);
fclose(file);
return NULL;
}

if (offset > size) {
dlt_log(LOG_WARNING, "file too long for buffer\n");
free(string);
fclose(file);
return NULL;
}
}

off_t offset = 0;
string[offset] = '\0'; /* append null termination at end of string */

while (!feof(f)) {
offset += (off_t) fread(version + offset, 1, (size_t) size, f);
return string;
}

if (ferror(f)) {
dlt_log(LOG_WARNING, "Failed to read ECU Software version file.\n");
free(version);
fclose(f);
return -1;
static char* file_read_field(FILE* const file, const char* const fieldName)
{
if (!file) {
return NULL;
}

const char* const kDelimiters = "\r\n\"\'=";
const size_t fieldNameLen = strlen(fieldName);

char* result = NULL;

char* buffer = NULL;
ssize_t bufferSize = 0;

while (true) {
ssize_t lineSize = getline(&buffer, &bufferSize, file);
if (lineSize < 0 || !buffer) {
/* end of file */
break;
}

if (offset > size) {
dlt_log(LOG_WARNING, "Too long file for ECU Software version info.\n");
free(version);
fclose(f);
return -1;
char* line = buffer;

/* trim trailing delimiters */
while (lineSize >= 1 && strchr(kDelimiters, line[lineSize - 1]) != NULL) {
line[lineSize - 1] = '\0';
--lineSize;
}

/* check fieldName */
if ( strncmp(line, fieldName, fieldNameLen) == 0
&& lineSize >= (fieldNameLen + 1)
&& strchr(kDelimiters, line[fieldNameLen]) != NULL
) {
/* trim fieldName */
line += fieldNameLen;

/* trim delimiter */
++line;

/* trim leading delimiters */
while (*line != '\0' && strchr(kDelimiters, *line) != NULL) {
++line;
--lineSize;
}

result = strdup(line);
break;
}
}

version[offset] = '\0';/*append null termination at end of version string */
daemon->ECUVersionString = version;
free(buffer);

return result;
}

int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
{
FILE *f = NULL;

PRINT_FUNCTION_VERBOSE(verbose);

/* By default, version string is null. */
daemon->ECUVersionString = NULL;

/* Open the file. Bail out if error occurs */
f = fopen(daemon_local->flags.pathToECUSoftwareVersion, "r");

if (f == NULL) {
/* Error level notice, because this might be deliberate choice */
dlt_log(LOG_NOTICE, "Failed to open ECU Software version file.\n");
return -1;
}

if (daemon_local->flags.ecuSoftwareVersionFileField[0] != '\0') {
daemon->ECUVersionString = file_read_field(f, daemon_local->flags.ecuSoftwareVersionFileField);
} else {
daemon->ECUVersionString = file_read_everything(f, DLT_DAEMON_TEXTBUFSIZE);
}

fclose(f);
return 0;

return (daemon->ECUVersionString != NULL) ? 0 : -1;
}

void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
Expand Down
1 change: 1 addition & 0 deletions src/daemon/dlt-daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ typedef struct
int loggingFileMaxSize; /**< (int) Maximum size in bytes of all logging files (Default: 1000000) */
int sendECUSoftwareVersion; /**< (Boolean) Send ECU software version perdiodically */
char pathToECUSoftwareVersion[DLT_DAEMON_FLAG_MAX]; /**< (String: Filename) The file from which to read the ECU version from. */
char ecuSoftwareVersionFileField[DLT_DAEMON_FLAG_MAX]; /**< Reads a specific VALUE from a FIELD=VALUE ECU version file. */
int sendTimezone; /**< (Boolean) Send Timezone perdiodically */
int offlineLogstorageMaxDevices; /**< (int) Maximum devices to be used as offline logstorage devices */
char offlineLogstorageDirPath[DLT_MOUNT_PATH_MAX]; /**< (String: Directory) DIR path to store offline logs */
Expand Down
3 changes: 3 additions & 0 deletions src/daemon/dlt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ ControlSocketPath = /tmp/dlt-ctrl.sock
# Absolute path to file storing version info - otherwise DLT version is used
# PathToECUSoftwareVersion = <absolute-path-to-file>

# Line prefix to read from software version file. Reads entire file if unset.
# ECUSoftwareVersionFileField = VERSION

########################################################################
# Timezone info #
########################################################################
Expand Down

0 comments on commit 7a55368

Please sign in to comment.