Files
can-utils/isobusfs/isobusfs_srv_cm_fss.c
T
Oliver Hartkopp 8355b57133 isobusfs: fix printf format specifiers in log messages
Several log messages used format specifiers which did not match the
types of the provided arguments (e.g. %d or %i for size_t/ssize_t,
%ld for int64_t/time_t and size_t for the '.*' precision). On 64 bit
hosts (and for int64_t/time_t on 32 bit hosts) this leads to wrong
output or undefined behaviour when the log level is enabled.

Additionally the seek response position was compared to the requested
offset without le32toh() conversion which fails on big endian hosts.

Fix the format specifiers and add the missing le32toh() conversion.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2026-10-14 19:25:06 +02:00

127 lines
3.7 KiB
C

// SPDX-License-Identifier: LGPL-2.0-only
// SPDX-FileCopyrightText: 2023 Oleksij Rempel <linux@rempel-privat.de>
/*
* This file implements Annex C.1.2 File Server Status according to
* ISO 11783-13:2021.
*/
#include <err.h>
#include <errno.h>
#include <inttypes.h>
#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "isobusfs_srv.h"
/*
* isobusfs_srv_fss_init - Initialize the file server status structure
* @priv: Pointer to the private data structure of the ISOBUS file server
*
* This function initializes the file server status structure, which
* represents the status of the file server according to Annex C.1.2
* of ISO 11783-13:2021.
*/
void isobusfs_srv_fss_init(struct isobusfs_srv_priv *priv)
{
struct isobusfs_cm_fss *st = &priv->st;
st->fs_function =
isobusfs_cg_function_to_buf(ISOBUSFS_CG_CONNECTION_MANAGMENT,
ISOBUSFS_CM_F_FS_STATUS);
st->status = 0;
st->num_open_files = 0;
memset(st->reserved, 0xFF, sizeof(st->reserved));
}
/*
* isobusfs_srv_fss_get_rate - Get the rate of File Server Status transmission
* @priv: Pointer to the private data structure of the ISOBUS file server
*
* Returns: the transmission rate of the File Server Status messages depending
* on the current state of the file server.
*/
static unsigned int isobusfs_srv_fss_get_rate(struct isobusfs_srv_priv *priv)
{
switch (priv->st_state) {
case ISOBUSFS_SRV_STATE_IDLE:
return ISOBUSFS_CM_F_FS_STATUS_IDLE_RATE;
/*
* On every change of Byte 2 "File Server Status" send max 5 status
* messages per second.
*/
case ISOBUSFS_SRV_STATE_STAT_CHANGE_1: /* fall through */
case ISOBUSFS_SRV_STATE_STAT_CHANGE_2: /* fall through */
case ISOBUSFS_SRV_STATE_STAT_CHANGE_3: /* fall through */
case ISOBUSFS_SRV_STATE_STAT_CHANGE_4: /* fall through */
case ISOBUSFS_SRV_STATE_STAT_CHANGE_5:
priv->st_state--;
return ISOBUSFS_CM_F_FS_STATUS_BUSY_RATE;
case ISOBUSFS_SRV_STATE_BUSY:
return ISOBUSFS_CM_F_FS_STATUS_BUSY_RATE;
default:
pr_warn("%s:%i: unknown state %d", __func__, __LINE__,
priv->st_state);
}
/*
* In case something is wrong, fall back to idle rate to not spam the
* bus.
*/
return ISOBUSFS_CM_F_FS_STATUS_IDLE_RATE;
}
/**
* isobusfs_srv_fss_send - Send periodic File Server Status messages
* @priv: Pointer to the private data structure of the ISOBUS file server
*
* Returns: 0 if the message was sent successfully, a negative error code
* otherwise.
*/
int isobusfs_srv_fss_send(struct isobusfs_srv_priv *priv)
{
unsigned int next_msg_rate;
int64_t time_diff;
int ret;
/* Test if it is proper time to send next status message. */
time_diff = timespec_diff_ms(&priv->cmn.next_send_time,
&priv->cmn.last_time);
if (time_diff > ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
/* too early to send next message */
return 0;
}
if (time_diff < -ISOBUSFS_CM_F_FS_STATUS_RATE_JITTER) {
pr_warn("too late to send next fs status message: %" PRId64 " ms",
time_diff);
}
/* Make sure we send the message with the latest stats */
if (priv->st_msg_stats.tskey_sch != priv->st_msg_stats.tskey_ack)
pr_warn("previous message was not acked");
/* send periodic file servers status messages. */
ret = send(priv->sock_fss, &priv->st, sizeof(priv->st), MSG_DONTWAIT);
if (ret < 0) {
ret = -errno;
pr_warn("Failed to send FS status message, error code: %d (%s)",
ret, strerror(ret));
return ret;
}
pr_debug("> tx FS status: 0x%02x, opened files: %d",
priv->st.status, priv->st.num_open_files);
/* Calculate time for the next status message */
next_msg_rate = isobusfs_srv_fss_get_rate(priv);
priv->cmn.next_send_time = priv->cmn.last_time;
timespec_add_ms(&priv->cmn.next_send_time, next_msg_rate);
return 0;
}