New Upstream Release - ledmon

Ready changes

Summary

Merged new upstream version: 0.96 (was: 0.95).

Resulting package

Built on 2022-12-18T05:19 (took 4m12s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases ledmon-dbgsymapt install -t fresh-releases ledmon

Lintian Result

Diff

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a82bac..04774f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+### v0.96 / 2022-05-26
+
+[Commit list](https://github.com/intel/ledmon/compare/v0.95...v0.96)
+
+Bug fixes
+
+* Manual updates, clarify --listed-only option
+* Fix cache indexing of ATA port
+* Fixes in regard to macros
+* Fix memory leak in amd_ipmi.c
+* Fix NULL pointer dereferences in sysfs.c
+* Make messages appear in service log immediately
+* Other minor fixes
+
 ### v0.95 / 2021-01-15
 
 [Commit list](https://github.com/intel/ledmon/compare/v0.94...v0.95)
diff --git a/Makefile.am b/Makefile.am
index d89b16a..d2b6f3a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 #
 #  Intel(R) Enclosure LED Utilities
-#  Copyright (C) 2009-2021 Intel Corporation.
+#  Copyright (C) 2009-2022 Intel Corporation.
 #
 #  This program is free software; you can redistribute it and/or modify it
 #  under the terms and conditions of the GNU General Public License,
diff --git a/README.md b/README.md
index d2684c0..56bfd0f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# This package contains the Enclosure LED Utilities, version 0.95
+# This package contains the Enclosure LED Utilities, version 0.96
 
-Copyright (C) 2009-2021 Intel Corporation.
+Copyright (C) 2009-2022 Intel Corporation.
 
 All files in this package can be freely distributed and used according
 to the terms of the GNU General Public License, version 2.
diff --git a/configure.ac b/configure.ac
index 8fd5e6b..001a049 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,8 +1,8 @@
 
 AC_PREREQ([2.69])
-AC_INIT([ledmon], [0.95])
+AC_INIT([ledmon], [0.96])
 AC_CONFIG_MACRO_DIR([m4])
-AC_SUBST([PACKAGE_DATE], "January 2021")
+AC_SUBST([PACKAGE_DATE], "May 2022")
 AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 
 # Checks for programs.
diff --git a/debian/changelog b/debian/changelog
index 0bc7ef4..5ba7a77 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+ledmon (0.96-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Sun, 18 Dec 2022 05:16:23 -0000
+
 ledmon (0.95-2) unstable; urgency=medium
 
   * Rebuild with libsgutils2-2 to fix broken dependency. (Closes: #994521)
diff --git a/debian/patches/0002-To-cast-uint64_t-for-shift-to-prevent-Werror-shift-c.patch b/debian/patches/0002-To-cast-uint64_t-for-shift-to-prevent-Werror-shift-c.patch
index 26ee1bf..47a15e9 100644
--- a/debian/patches/0002-To-cast-uint64_t-for-shift-to-prevent-Werror-shift-c.patch
+++ b/debian/patches/0002-To-cast-uint64_t-for-shift-to-prevent-Werror-shift-c.patch
@@ -6,11 +6,11 @@ Subject: To cast uint64_t for shift to prevent -Werror=shift-count-overflow
  src/amd_sgpio.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
-diff --git a/src/amd_sgpio.c b/src/amd_sgpio.c
-index 8150e4c..e496e5a 100644
---- a/src/amd_sgpio.c
-+++ b/src/amd_sgpio.c
-@@ -49,7 +49,7 @@
+Index: ledmon.git/src/amd_sgpio.c
+===================================================================
+--- ledmon.git.orig/src/amd_sgpio.c
++++ ledmon.git/src/amd_sgpio.c
+@@ -47,7 +47,7 @@
  
  #define DECLARE_SGPIO(type, name, shift, mask)				\
  	uint32_t	_##type##_##name##_shift = shift;		\
diff --git a/doc/Makefile.am b/doc/Makefile.am
index f894cf5..84d203d 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,6 +1,6 @@
 #
 #  Intel(R) Enclosure LED Utilities
-#  Copyright (C) 2009-2021 Intel Corporation.
+#  Copyright (C) 2009-2022 Intel Corporation.
 #
 #  This program is free software; you can redistribute it and/or modify it
 #  under the terms and conditions of the GNU General Public License,
diff --git a/doc/ledctl.pod b/doc/ledctl.pod
index 337280c..774d04b 100644
--- a/doc/ledctl.pod
+++ b/doc/ledctl.pod
@@ -1,6 +1,6 @@
 #
 #  Intel(R) Enclosure LED Utilities
-#  Copyright (C) 2009-2021 Intel Corporation.
+#  Copyright (C) 2009-2022 Intel Corporation.
 #
 #  This program is free software; you can redistribute it and/or modify it
 #  under the terms and conditions of the GNU General Public License,
@@ -297,12 +297,9 @@ list> in curly braces and elements are separated by space. See examples
 section below for details.
 
 A device is a path to file in /dev directory or in /sys/block directory.
-It may identify a block device, a RAID device or a container device.
-In case of a RAID device or a container device a state will be set for all
-block devices associated, respectively.
 
 The LEDs of devices listed in I<list_of_devices> are set to the given
-pattern I<pattern_name> and all other LEDs are turned off (unless --listed-only
+pattern I<pattern_name> and all other LEDs, on all devices, are turned off (unless --listed-only
 option is given).
 
 =head1 OPTIONS
@@ -354,33 +351,44 @@ to user defined file use I<-l> option switch.
 
 =head1 EXAMPLES
 
-The following example illustrates how to locate a single block device.
+The following example illustrates how to set I<locate> on a single
+block device. Note that all remaining LEDs, on all devices, will be turned off.
 
     ledctl locate=/dev/sda
 
-The following example illustrates how to turn Locate LED off for the same block device.
+The following example illustrates how to set I<locate_off> on a single
+block device.
 
-    ledctl locate_off=/dev/sda
+    ledctl --listed-only locate_off=/dev/sda
 
-The following example illustrates how to locate disks of a RAID device and
-how to set rebuild pattern for two block devices at the same time. This example
-uses both formats of device list.
+The following example illustrates how to set I<off> on the given devices. It
+uses second format of device list.
 
-     ledctl locate=/dev/md127 rebuild={ /sys/block/sd[a-b] }
+     ledctl --listed-only off={ /dev/sda /dev/sdb }
 
-The following example illustrates how to turn Status LED and Failure LED off for
-the given device(s).
+The following example illustrates how to set I<locate> and I<rebuild> on
+different devices at the same time. It uses the second format of device list.
 
-     ledctl off={ /dev/sda /dev/sdb }
+     ledctl --listed-only locate={ /dev/sdb } rebuild={ /sys/block/sdc }
 
-The following example illustrates how to locate a three block devices. This
-example uses the first format of device list.
+The following example illustrates how to I<locate> on three block devices. It
+uses the first format of device list.
 
-     ledctl locate=/dev/sda,/dev/sdb,/dev/sdc
+     ledctl --listed-only locate=/dev/sda,/dev/sdb,/dev/sdc
+
+The following example illustrates how to set I<locate> and I<rebuild> on
+different devices at the same time. It uses the first format of device list.
+
+     ledctl --listed-only locate=/dev/sdb rebuild=/sys/block/sdc
+
+The following example illustrates how to set I<locate> and I<rebuild> on
+different devices at the same time. It uses the both formats of device list.
+
+     ledctl --listed-only locate={ /dev/sdb } rebuild=/sys/block/sdc
 
 =head1 LICENSE
 
-Copyright (c) 2009-2021 Intel Corporation.
+Copyright (c) 2009-2022 Intel Corporation.
 
 This program is distributed under the terms of the GNU General Public License
 as published by the Free Software Foundation. See the built-in help for
diff --git a/doc/ledmon.conf.pod b/doc/ledmon.conf.pod
index 478bee0..a80826d 100644
--- a/doc/ledmon.conf.pod
+++ b/doc/ledmon.conf.pod
@@ -45,6 +45,7 @@ See also the examples section.
 B<BLACKLIST> - Ledmon will exclude scanning controllers listed on blacklist.
 When whitelist is also set in config file, the blacklist will be ignored.
 The controllers should be separated by comma (B<,>) character.
+The B<XBD Extended Regular Expressions> are supported.
 
 B<BLINK_ON_INIT> - Related with RAID Initialization (resync), Verify (check)
 and Verify and Fix (repair) processes. If value is set to true - status LEDs of
@@ -82,6 +83,7 @@ that is during rebuild will blink during this operation.
 B<WHITELIST> - Ledmon will limit changing LED state to controllers listed on
 whitelist. If any whitelist is set, only devices from list will be scanned by
 ledmon. The controllers should be separated by comma (B<,>) character.
+The B<XBD Extended Regular Expressions> are supported.
 
 =head1 EXAMPLES
 
diff --git a/doc/ledmon.pod b/doc/ledmon.pod
index 3b40492..de12895 100644
--- a/doc/ledmon.pod
+++ b/doc/ledmon.pod
@@ -1,6 +1,6 @@
 #
 #  Intel(R) Enclosure LED Utilities
-#  Copyright (C) 2009-2021 Intel Corporation.
+#  Copyright (C) 2009-2022 Intel Corporation.
 #
 #  This program is free software; you can redistribute it and/or modify it
 #  under the terms and conditions of the GNU General Public License,
@@ -183,7 +183,7 @@ switch.
 
 =head1 LICENSE
 
-Copyright (c) 2009-2021 Intel Corporation.
+Copyright (c) 2009-2022 Intel Corporation.
 
 This program is distributed under the terms of the GNU General Public License
 as published by the Free Software Foundation. See the build-in help for details
diff --git a/src/Makefile.am b/src/Makefile.am
index 3d78d30..f778620 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
 #
 #  Intel(R) Enclosure LED Utilities
-#  Copyright (C) 2009-2021 Intel Corporation.
+#  Copyright (C) 2009-2022 Intel Corporation.
 #
 #  This program is free software; you can redistribute it and/or modify it
 #  under the terms and conditions of the GNU General Public License,
diff --git a/src/ahci.c b/src/ahci.c
index 49a9ace..00e8ee7 100644
--- a/src/ahci.c
+++ b/src/ahci.c
@@ -87,7 +87,7 @@ int ahci_sgpio_write(struct block_device *device, enum ibpi_pattern ibpi)
 	if ((ibpi < IBPI_PATTERN_NORMAL) || (ibpi > IBPI_PATTERN_LOCATE_OFF))
 		__set_errno_and_return(ERANGE);
 
-	sprintf(temp, "%u", ibpi2sgpio[ibpi]);
+	snprintf(temp, WRITE_BUFFER_SIZE, "%u", ibpi2sgpio[ibpi]);
 
 	snprintf(path, sizeof(path), "%s/em_message", sysfs_path);
 
@@ -102,28 +102,30 @@ int ahci_sgpio_write(struct block_device *device, enum ibpi_pattern ibpi)
 
 char *ahci_get_port_path(const char *path)
 {
-	char *p;
-	char tmp[PATH_MAX];
+	char *target_p, *host_p;
+	size_t host_length, length_to_target;
 	char *buf;
-	size_t buf_size;
 
-	p = strstr(path, "/target");
-	if (p == NULL)
+	host_p = strstr(path, "/host");
+	if (host_p == NULL)
 		return NULL;
 
-	if (sizeof(tmp) <= (p - path))
+	target_p = strstr(host_p, "/target");
+	if (target_p == NULL)
 		return NULL;
-	strncpy(tmp, path, p - path);
-	tmp[p - path] = '\0';
-	p = strrchr(tmp, PATH_DELIM);
-	if (p == NULL)
+
+	length_to_target = target_p - path;
+	host_length = target_p - host_p;
+
+	if (host_length + length_to_target + strlen(SCSI_HOST) > PATH_MAX - 1)
 		return NULL;
 
-	buf_size = strlen(tmp) + strlen(p) + strlen(SCSI_HOST) + 1;
-	buf = malloc(buf_size);
+	buf = calloc(PATH_MAX, sizeof(char));
 	if (buf == NULL)
 		return NULL;
 
-	snprintf(buf, buf_size, "%s%s%s", tmp, SCSI_HOST, p);
+	strncpy(buf, path, length_to_target);
+	strncat(buf, SCSI_HOST, strlen(SCSI_HOST) + 1);
+	strncat(buf, host_p, host_length);
 	return buf;
 }
diff --git a/src/amd.c b/src/amd.c
index 85f3a9a..7fe71b5 100644
--- a/src/amd.c
+++ b/src/amd.c
@@ -1,6 +1,6 @@
 /*
  * AMD LED control
- * Copyright (C) 2021, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/src/amd.h b/src/amd.h
index 8f0ce12..290732c 100644
--- a/src/amd.h
+++ b/src/amd.h
@@ -1,6 +1,6 @@
 /*
  * AMD LED control
- * Copyright (C) 2021, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/src/amd_ipmi.c b/src/amd_ipmi.c
index 25bef40..7b0a7e1 100644
--- a/src/amd_ipmi.c
+++ b/src/amd_ipmi.c
@@ -1,6 +1,6 @@
 /*
  * AMD IPMI LED control
- * Copyright (C) 2021, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -52,6 +52,17 @@ static uint8_t amd_ibpi_ipmi_register[] = {
 	[IBPI_PATTERN_HOTSPARE] = 0x47,
 };
 
+#define MG9098_CHIP_ID_REG	0x63
+
+#define AMD_IPMI_NETFN		0x06
+#define AMD_IPMI_CMD		0x52
+
+#define AMD_ETHANOL_X_CHANNEL	0x0d
+#define AMD_DAYTONA_X_CHANNEL	0x17
+
+#define AMD_BASE_SLAVE_ADDR	0xc0
+#define AMD_NVME_SLAVE_ADDR	0xc4
+
 /* The path we are given should be similar to
  * /sys/devices/pci0000:e0/0000:e0:03.3/0000:e3:00.0
  *                                      ^^^^^^^^^^
@@ -95,7 +106,8 @@ static int _get_ipmi_nvme_port(char *path)
 			char *dname = strrchr(dir_path, '/');
 
 			dname++;
-			port = strtol(dname, NULL, 0);
+			if (str_toi(&port, dname, NULL, 0) != 0)
+				return -1;
 			break;
 		}
 	}
@@ -148,7 +160,8 @@ static int _get_ipmi_sata_port(const char *start_path)
 
 	/* skip past 'ata' to get the ata port number */
 	t += 3;
-	port = strtoul(t, NULL, 10);
+	if (str_toi(&port, t, NULL, 10) != 0)
+		return -1;
 
 	return port;
 }
@@ -204,10 +217,10 @@ static int _ipmi_platform_channel(struct amd_drive *drive)
 
 	switch (amd_ipmi_platform) {
 	case AMD_PLATFORM_ETHANOL_X:
-		drive->channel =  0xd;
+		drive->channel = AMD_ETHANOL_X_CHANNEL;
 		break;
 	case AMD_PLATFORM_DAYTONA_X:
-		drive->channel = 0x17;
+		drive->channel = AMD_DAYTONA_X_CHANNEL;
 		break;
 	default:
 		rc = -1;
@@ -224,27 +237,27 @@ static int _ipmi_platform_slave_address(struct amd_drive *drive)
 
 	switch (amd_ipmi_platform) {
 	case AMD_PLATFORM_ETHANOL_X:
-		drive->slave_addr = 0xc0;
+		drive->slave_addr = AMD_BASE_SLAVE_ADDR;
 		break;
 	case AMD_PLATFORM_DAYTONA_X:
 		if (drive->dev == AMD_NO_DEVICE) {
 			/* Assume base slave address, we may not be able
 			 * to retrieve a valid amd_drive yet.
 			 */
-			drive->slave_addr = 0xc0;
+			drive->slave_addr = AMD_BASE_SLAVE_ADDR;
 		} else if (drive->dev == AMD_NVME_DEVICE) {
 			/* On DaytonaX systems only drive bays 19 - 24
 			 * support NVMe devices so use the slave address
 			 * for the corresponding MG9098 chip.
 			 */
-			drive->slave_addr = 0xc4;
+			drive->slave_addr = AMD_NVME_SLAVE_ADDR;
 		} else {
 			if (drive->port <= 8)
-				drive->slave_addr = 0xc0;
+				drive->slave_addr = AMD_BASE_SLAVE_ADDR;
 			else if (drive->port > 8 && drive->port < 17)
-				drive->slave_addr = 0xc2;
+				drive->slave_addr = AMD_BASE_SLAVE_ADDR + 2;
 			else
-				drive->slave_addr = 0xc4;
+				drive->slave_addr = AMD_NVME_SLAVE_ADDR;
 		}
 
 		break;
@@ -285,8 +298,8 @@ static int _set_ipmi_register(int enable, uint8_t reg,
 	log_debug(REG_FMT_2, "channel", cmd_data[0], "slave addr", cmd_data[1]);
 	log_debug(REG_FMT_2, "len", cmd_data[2], "register", cmd_data[3]);
 
-	rc = ipmicmd(BMC_SA, 0x0, 0x6, 0x52, 4, &cmd_data, 1, &data_sz,
-		     &status);
+	rc = ipmicmd(BMC_SA, 0x0, AMD_IPMI_NETFN, AMD_IPMI_CMD, 4, &cmd_data,
+		     1, &data_sz, &status);
 	if (rc) {
 		log_error("Could not determine current register %x setting\n",
 			  reg);
@@ -310,8 +323,8 @@ static int _set_ipmi_register(int enable, uint8_t reg,
 	log_debug(REG_FMT_2, "len", cmd_data[2], "register", cmd_data[3]);
 	log_debug(REG_FMT_1, "status", cmd_data[4]);
 
-	rc = ipmicmd(BMC_SA, 0x0, 0x6, 0x52, 5, &cmd_data, 1, &data_sz,
-		     &status);
+	rc = ipmicmd(BMC_SA, 0x0, AMD_IPMI_NETFN, AMD_IPMI_CMD, 5, &cmd_data,
+		     1, &data_sz, &status);
 	if (rc) {
 		log_error("Could not enable register %x\n", reg);
 		return rc;
@@ -368,19 +381,20 @@ int _amd_ipmi_em_enabled(const char *path)
 	cmd_data[0] = drive.channel;
 	cmd_data[1] = drive.slave_addr;
 	cmd_data[2] = 0x1;
-	cmd_data[3] = 0x63;
+	cmd_data[3] = MG9098_CHIP_ID_REG;
 
 	status = 0;
-	rc = ipmicmd(BMC_SA, 0x0, 0x6, 0x52, 4, &cmd_data, 1,
-		     &data_sz, &status);
+	rc = ipmicmd(BMC_SA, 0x0, AMD_IPMI_NETFN, AMD_IPMI_CMD, 4, &cmd_data,
+		     1, &data_sz, &status);
 
 	if (rc) {
 		log_error("Can't determine MG9098 Status for AMD platform\n");
 		return 0;
 	}
 
+	/* Status return of 98 indicates MG9098 backplane */
 	if (status != 98) {
-		log_error("Platform %s does not have a MG9098 controller\n");
+		log_error("Platform does not have a MG9098 controller\n");
 		return 0;
 	}
 
@@ -423,20 +437,16 @@ int _amd_ipmi_write(struct block_device *device, enum ibpi_pattern ibpi)
 
 char *_amd_ipmi_get_path(const char *cntrl_path, const char *sysfs_path)
 {
-	char *p, *t;
+	char *t;
 
 	/* For NVMe devices we can just dup the path sysfs path */
-	p = strstr(cntrl_path, "nvme");
-	if (p)
+	if (strstr(cntrl_path, "nvme"))
 		return strdup(sysfs_path);
 
-	/* For SATA devices we need everything up to 'ataXX/' in the path */
-	p = strdup(cntrl_path);
-	if (!p)
-		return NULL;
-
-	/* Find the beginning of the ataXX piece of the path */
-	t = strstr(p, "ata");
+	/*
+	 * For SATA devices we need everything up to 'ataXX/' in the path
+	 */
+	t = strstr(cntrl_path, "ata");
 	if (!t)
 		return NULL;
 
@@ -447,8 +457,6 @@ char *_amd_ipmi_get_path(const char *cntrl_path, const char *sysfs_path)
 	if (!t)
 		return NULL;
 
-	*++t = '\0';
-
-	return p;
+	return strndup(cntrl_path, (t - cntrl_path) + 1);
 }
 
diff --git a/src/amd_sgpio.c b/src/amd_sgpio.c
index 9b1fc6c..235624c 100644
--- a/src/amd_sgpio.c
+++ b/src/amd_sgpio.c
@@ -275,7 +275,7 @@ static struct cache_entry *_get_cache(struct amd_drive *drive)
 	 *	cache_entry[n] => drive (4*n) to drive (4*n + 3)
 	 */
 
-	index = (drive->ata_port / 4);
+	index = ((drive->ata_port - 1) / 4);
 
 	return &sgpio_cache[index];
 }
@@ -569,7 +569,8 @@ static int _get_amd_sgpio_drive(const char *start_path,
 
 	/* skip past 'ata' to get the ata port number */
 	a += 3;
-	drive->ata_port = strtoul(a, NULL, 10);
+	if (str_toi(&drive->ata_port, a, NULL, 10) != 0)
+		return -1;
 
 	found = _find_file_path(ata_dir, "port_no", path, PATH_MAX);
 	if (!found) {
diff --git a/src/block.c b/src/block.c
index 2174acb..c61c577 100644
--- a/src/block.c
+++ b/src/block.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -190,7 +190,7 @@ struct cntrl_device *block_get_controller(const struct list *cntrl_list, char *p
 
 	list_for_each(cntrl_list, cntrl) {
 		if (strncmp(cntrl->sysfs_path, path,
-			    strlen(cntrl->sysfs_path)) == 0) {
+			    strnlen(cntrl->sysfs_path, PATH_MAX)) == 0) {
 			if (cntrl->cntrl_type == CNTRL_TYPE_NPEM)
 				return cntrl;
 			non_npem_cntrl = cntrl;
diff --git a/src/cntrl.c b/src/cntrl.c
index 6b73dac..f54d880 100644
--- a/src/cntrl.c
+++ b/src/cntrl.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -119,10 +119,12 @@ static int _is_amd_nvme_cntrl(const char *path)
 	char tmp[PATH_MAX];
 	char *t;
 
+	memset(&tmp, 0, sizeof(tmp));
+
 	if (!_is_nvme_cntrl(path))
 		return 0;
 
-	sprintf(tmp, "%s", path);
+	strncpy(tmp, path, PATH_MAX - 1);
 	t = strrchr(tmp, '/');
 	if (!t)
 		return 0;
@@ -435,7 +437,7 @@ struct cntrl_device *cntrl_device_init(const char *path)
 			em_enabled = 0;
 		}
 		if (em_enabled) {
-			device = malloc(sizeof(struct cntrl_device));
+			device = calloc(1, sizeof(struct cntrl_device));
 			if (device) {
 				if (type == CNTRL_TYPE_SCSI) {
 					device->isci_present = _is_isci_cntrl(path);
@@ -445,7 +447,7 @@ struct cntrl_device *cntrl_device_init(const char *path)
 					device->hosts = NULL;
 				}
 				device->cntrl_type = type;
-				device->sysfs_path = str_dup(path);
+				strncpy(device->sysfs_path, path, PATH_MAX - 1);
 			}
 		} else {
 			log_error
@@ -463,7 +465,6 @@ struct cntrl_device *cntrl_device_init(const char *path)
 void cntrl_device_fini(struct cntrl_device *device)
 {
 	if (device) {
-		free(device->sysfs_path);
 		free_hosts(device->hosts);
 		free(device);
 	}
diff --git a/src/cntrl.h b/src/cntrl.h
index ff1a3ec..b44a212 100644
--- a/src/cntrl.h
+++ b/src/cntrl.h
@@ -20,6 +20,8 @@
 #ifndef _CNTRL_H_INCLUDED_
 #define _CNTRL_H_INCLUDED_
 
+#include <limits.h>
+
 /**
  * This enumeration type lists all supported storage controller types.
  */
@@ -42,7 +44,7 @@ struct cntrl_device {
 	/**
 	* Path to the device in sysfs tree.
 	*/
-	char *sysfs_path;
+	char sysfs_path[PATH_MAX];
 
 	/**
 	 * Type of storage controller device.
diff --git a/src/config_file.c b/src/config_file.c
index 3af0c92..95ea335 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -1,7 +1,7 @@
 /*
  * Intel(R) Enclosure LED Utilities
  *
- * Copyright (C) 2017-2021 Intel Corporation.
+ * Copyright (C) 2017-2022 Intel Corporation.
  * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
  *
  * SPDX-License-Identifier: GPL-2.0
@@ -143,8 +143,8 @@ static int parse_next(FILE *fd)
 	if (!strncmp(s, "INTERVAL=", 9)) {
 		s += 9;
 		if (*s) {
-			if (sscanf(s, "%d", &conf.scan_interval) != 1 ||
-			    conf.scan_interval < LEDMON_MIN_SLEEP_INTERVAL)
+			if (str_toi(&conf.scan_interval, s, NULL, 10) != 0 ||
+				conf.scan_interval < LEDMON_MIN_SLEEP_INTERVAL)
 				conf.scan_interval = LEDMON_MIN_SLEEP_INTERVAL;
 		}
 	} else if (!strncmp(s, "LOG_LEVEL=", 10)) {
@@ -205,14 +205,14 @@ int ledmon_read_config(const char *filename)
 
 	if (!filename || (filename && access(filename, F_OK) < 0)) {
 		if (filename)
-			fprintf(stdout, "%s: does not exist, using global config file\n",
+			fprintf(stderr, "%s: does not exist, using global config file\n",
 				filename);
 		filename = LEDMON_DEF_CONF_FILE;
 	}
 
 	f = fopen(filename, "re");
 	if (!f) {
-		fprintf(stdout, "%s: does not exist, using built-in defaults\n",
+		fprintf(stderr, "%s: does not exist, using built-in defaults\n",
 			filename);
 	} else {
 		while (!feof(f)) {
@@ -228,7 +228,7 @@ int ledmon_read_config(const char *filename)
 
 	if (!list_is_empty(&conf.cntrls_whitelist) &&
 	    !list_is_empty(&conf.cntrls_blacklist))
-		fprintf(stdout, "Both whitelist and blacklist are specified - ignoring blacklist.");
+		fprintf(stderr, "Both whitelist and blacklist are specified - ignoring blacklist.");
 
 	return STATUS_SUCCESS;
 }
@@ -240,11 +240,8 @@ static char *conf_list_to_str(struct list *list)
 
 	memset(buf, 0, sizeof(buf));
 	list_for_each(list, elem) {
-		if (elem) {
-			int curr = strlen(buf);
-
-			snprintf(buf + curr, sizeof(buf) - curr, "%s,", elem);
-		}
+		int curr = strlen(buf);
+		snprintf(buf + curr, sizeof(buf) - curr, "%s,", elem);
 	}
 
 	return str_dup(buf);
diff --git a/src/enclosure.c b/src/enclosure.c
index 14c892f..c41f872 100644
--- a/src/enclosure.c
+++ b/src/enclosure.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -110,7 +110,7 @@ static char *_get_dev_sg(const char *encl_path)
  */
 struct enclosure_device *enclosure_device_init(const char *path)
 {
-	char temp[PATH_MAX];
+	char temp[PATH_MAX] = "\0";
 	struct enclosure_device *enclosure;
 	int ret;
 	int fd;
@@ -124,7 +124,7 @@ struct enclosure_device *enclosure_device_init(const char *path)
 		goto out;
 	}
 
-	enclosure->sysfs_path = str_dup(temp);
+	memccpy(enclosure->sysfs_path, temp, '\0', PATH_MAX - 1);
 	enclosure->sas_address = _get_sas_address(temp);
 	enclosure->dev_path = _get_dev_sg(temp);
 
@@ -157,7 +157,6 @@ void enclosure_device_fini(struct enclosure_device *enclosure)
 {
 	if (enclosure) {
 		free(enclosure->slots);
-		free(enclosure->sysfs_path);
 		free(enclosure->dev_path);
 		free(enclosure);
 	}
diff --git a/src/enclosure.h b/src/enclosure.h
index 6312a97..75e55ab 100644
--- a/src/enclosure.h
+++ b/src/enclosure.h
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -21,6 +21,7 @@
 #define _ENCLOSURE_H_INCLUDED_
 
 #include <stdint.h>
+#include <limits.h>
 
 #include "ses.h"
 
@@ -35,7 +36,7 @@ struct enclosure_device {
    * Path to an enclosure device in sysfs tree. This is controller base
    * canonical path.
    */
-	char *sysfs_path;
+	char sysfs_path[PATH_MAX];
 
   /**
    * SAS address as identifier of an enclosure.
diff --git a/src/ledctl.c b/src/ledctl.c
index ce32d86..caedc1a 100644
--- a/src/ledctl.c
+++ b/src/ledctl.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -96,7 +96,7 @@ const char *ibpi_str[] = {
  * information about the version of ledctl utility.
  */
 static char *ledctl_version = "Intel(R) Enclosure LED Control Application %s %s\n"
-			      "Copyright (C) 2009-2021 Intel Corporation.\n";
+			      "Copyright (C) 2009-2022 Intel Corporation.\n";
 
 /**
  * Internal variable of monitor service. It is used to help parse command line
@@ -441,7 +441,7 @@ static status_t _ibpi_state_add_block(struct ibpi_state *state, char *name)
 	if (strstr(temp, "/dev/") != NULL) {
 		if (stat(temp, &st) < 0)
 			return STATUS_STAT_ERROR;
-		sprintf(temp, "/sys/dev/block/%u:%u", major(st.st_rdev),
+		snprintf(temp, PATH_MAX, "/sys/dev/block/%u:%u", major(st.st_rdev),
 			minor(st.st_rdev));
 		if ((realpath(temp, path) == NULL) && (errno != ENOTDIR))
 			return STATUS_INVALID_PATH;
diff --git a/src/ledmon.c b/src/ledmon.c
index 1ab205c..885e028 100644
--- a/src/ledmon.c
+++ b/src/ledmon.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -119,7 +119,7 @@ const char *ibpi_str[] = {
  * information about the version of monitor service.
  */
 static char *ledmon_version = "Intel(R) Enclosure LED Monitor Service %s %s\n"
-			      "Copyright (C) 2009-2021 Intel Corporation.\n";
+			      "Copyright (C) 2009-2022 Intel Corporation.\n";
 
 /**
  * Internal variable of monitor service. It is used to help parse command line
@@ -292,9 +292,7 @@ static status_t _set_config_path(char **conf_path, const char *path)
  */
 static status_t _set_sleep_interval(const char *optarg)
 {
-	errno = 0;
-	conf.scan_interval = strtol(optarg, NULL, 10);
-	if (errno != 0) {
+	if (str_toi(&conf.scan_interval, optarg, NULL, 10) != 0) {
 		log_error("Cannot parse sleep interval");
 		return STATUS_CMDLINE_ERROR;
 	}
@@ -842,7 +840,10 @@ static void _close_parent_fds(void)
 		char *elem;
 
 		list_for_each(&dir, elem) {
-			int fd = (int)strtol(basename(elem), NULL, 10);
+			int fd;
+
+			if (str_toi(&fd, basename(elem), NULL, 10) != 0)
+				continue;
 
 			if (fd != get_log_fd())
 				close(fd);
diff --git a/src/list.c b/src/list.c
index d7b09a9..c0d6ede 100644
--- a/src/list.c
+++ b/src/list.c
@@ -59,6 +59,11 @@ void list_insert(struct list *list, void *item, struct node *after)
 	struct node *new;
 	struct node **x;
 
+	if (!item) {
+		log_error("Failed to insert item into list. NULL cannot be inserted.");
+		exit(1);
+	}
+
 	new = malloc(sizeof(struct node));
 	if (!new) {
 		log_error("Failed to allocate memory for list node.");
diff --git a/src/list.h b/src/list.h
index 87b8850..dff9ac9 100644
--- a/src/list.h
+++ b/src/list.h
@@ -48,7 +48,7 @@ struct list {
 
 #define __list_for_each(__list, __item, __start_fn, __iter_fn) \
 	for (struct node *__node = __start_fn(__list); \
-	     __node && ((__item = __node->item) || (!__node->item)); \
+	     __node && ((__item = __node->item) || (!__item)); \
 	     __node = __iter_fn(__node))
 
 #define list_for_each(__list, __item) \
diff --git a/src/npem.c b/src/npem.c
index 23b518d..4f836ee 100644
--- a/src/npem.c
+++ b/src/npem.c
@@ -84,11 +84,16 @@ static struct pci_dev *get_pci_dev(struct pci_access *pacc, const char *path)
 {
 	unsigned int domain, bus, dev, fn;
 	char *p = strrchr(path, '/');
+	int ret = 0;
 
 	if (!p)
 		return NULL;
 
-	if (sscanf(p + 1, "%x:%x:%x.%x", &domain, &bus, &dev, &fn) != 4)
+	ret += str_toui(&domain, p + 1, &p, 16);
+	ret += str_toui(&bus, p + 1, &p, 16);
+	ret += str_toui(&dev, p + 1, &p, 16);
+	ret += str_toui(&fn, p + 1, &p, 16);
+	if (ret != 0)
 		return NULL;
 
 	return pci_get_dev(pacc, domain, bus, dev, fn);
diff --git a/src/pidfile.c b/src/pidfile.c
index 5d0e230..ec4348b 100644
--- a/src/pidfile.c
+++ b/src/pidfile.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -56,7 +56,7 @@ status_t pidfile_create(const char *name)
 		close(fd);
 		return STATUS_FILE_LOCK_ERROR;
 	}
-	sprintf(buf, "%d\n", getpid());
+	snprintf(buf, PATH_MAX, "%d\n", getpid());
 	count = write(fd, buf, strlen(buf));
 	close(fd);
 	return (count < 0) ? STATUS_FILE_WRITE_ERROR : STATUS_SUCCESS;
@@ -99,7 +99,8 @@ status_t pidfile_check(const char *name, pid_t *pid)
 	p = buf_read(path);
 	if (p == NULL)
 		return STATUS_INVALID_PATH;
-	tp = strtol(p, NULL, 10);
+	if (str_toi(&tp, p, NULL, 10) != 0)
+		return STATUS_DATA_ERROR;
 	if (pid)
 		*pid = tp;
 	free(p);
diff --git a/src/scsi.c b/src/scsi.c
index 199ae3b..3c0a0c3 100644
--- a/src/scsi.c
+++ b/src/scsi.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -157,7 +157,7 @@ char *scsi_get_host_path(const char *path, const char *ctrl_path)
 {
 	char *host;
 	char host_path[PATH_MAX] = { 0 };
-	size_t ctrl_path_len = strlen(ctrl_path);
+	size_t ctrl_path_len = strnlen(ctrl_path, PATH_MAX);
 
 	if (strncmp(path, ctrl_path, ctrl_path_len) != 0)
 		return NULL;
diff --git a/src/scsi.h b/src/scsi.h
index 1e0dd72..60897f6 100644
--- a/src/scsi.h
+++ b/src/scsi.h
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/src/ses.c b/src/ses.c
index 75e1d5e..83690dd 100644
--- a/src/ses.c
+++ b/src/ses.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/src/ses.h b/src/ses.h
index 62ca482..802311b 100644
--- a/src/ses.h
+++ b/src/ses.h
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/src/slave.c b/src/slave.c
index 48f5276..41d6653 100644
--- a/src/slave.c
+++ b/src/slave.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -75,17 +75,21 @@ static unsigned int _get_errors(const char *path)
 
 /**
  */
-static unsigned int _get_slot(const char *path)
+static int _get_slot(const char *path, unsigned int *dest)
 {
-	unsigned int result = -1;
-
+	int ret = 1;
+	unsigned int n;
 	char *p = get_text(path, "slot");
+
 	if (p) {
 		if (strcmp(p, "none") != 0)
-			result = strtol(p, NULL, 10);
+			if (str_toui(&n, p, NULL, 10) == 0) {
+				*dest = n;
+				ret = 0;
+			}
 		free(p);
 	}
-	return result;
+	return ret;
 }
 
 /**
@@ -130,12 +134,14 @@ struct slave_device *slave_device_init(const char *path, struct list *block_list
 	block = _get_block(path, block_list);
 	if (block) {
 		device = malloc(sizeof(struct slave_device));
-		if (device) {
+		if (device && _get_slot(path, &device->slot) == 0) {
 			device->raid = NULL;
 			device->state = _get_state(path);
-			device->slot = _get_slot(path);
 			device->errors = _get_errors(path);
 			device->block = block;
+		} else {
+			free(device);
+			device = NULL;
 		}
 	}
 	return device;
diff --git a/src/smp.c b/src/smp.c
index 2c089f8..6cb132e 100644
--- a/src/smp.c
+++ b/src/smp.c
@@ -553,7 +553,7 @@ int cntrl_init_smp(const char *path, struct cntrl_device *cntrl)
 {
 	char *path2 = NULL;
 	char *c;
-	int host, port = 0;
+	int port = 0;
 	struct dirent *de;
 	DIR *d;
 
@@ -604,8 +604,11 @@ int cntrl_init_smp(const char *path, struct cntrl_device *cntrl)
 				/* Need link called "phy-XX:Y
 				 * Y is real phy we need.
 				 * This can also be found
-				 * in phy_identifier file */
-				if (sscanf(de->d_name, "phy-%d:%d", &host, &port) != 2)
+				 * in phy_identifier file
+				 */
+				char *s = strstr(de->d_name, ":") + 1;
+
+				if (str_toi(&port, s, NULL, 10) != 0)
 					continue;
 
 				break;
diff --git a/src/smp.h b/src/smp.h
index e2d7485..033db6b 100644
--- a/src/smp.h
+++ b/src/smp.h
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2011-2021 Intel Corporation.
+ * Copyright (C) 2011-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/src/sysfs.c b/src/sysfs.c
index d4622dc..87e8339 100644
--- a/src/sysfs.c
+++ b/src/sysfs.c
@@ -240,6 +240,10 @@ static void _slave_cnt_add(const char *path, struct raid_device *raid)
 	struct slave_device *device;
 
 	char *t = strrchr(path, '/');
+
+	if (!t)
+		return;
+
 	if (strncmp(t + 1, "dev-", 4) == 0) {
 		device = slave_device_init(path, &sysfs_block_list);
 		if (device) {
@@ -355,6 +359,10 @@ static void _slots_add(const char *path)
 static void _check_raid(const char *path)
 {
 	char *t = strrchr(path, '/');
+
+	if (!t)
+		return;
+
 	if (strncmp(t + 1, "md", 2) == 0)
 		_raid_add(path);
 }
@@ -645,9 +653,8 @@ int sysfs_enclosure_attached_to_cntrl(const char *path)
 	struct enclosure_device *device;
 
 	list_for_each(&enclo_list, device) {
-		if ((device->sysfs_path != NULL) &&
-		    (strncmp(device->sysfs_path, path, strlen(path)) == 0))
-			return 1;
+			if (strncmp(device->sysfs_path, path, strnlen(path, PATH_MAX)) == 0)
+				return 1;
 	}
 	return 0;
 }
diff --git a/src/utils.c b/src/utils.c
index 0f0b22f..7f52194 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,6 +1,6 @@
 /*
  * Intel(R) Enclosure LED Utilities
- * Copyright (C) 2009-2021 Intel Corporation.
+ * Copyright (C) 2009-2022 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -34,6 +34,7 @@
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
+#include <assert.h>
 
 #if _HAVE_DMALLOC_H
 #include <dmalloc.h>
@@ -92,34 +93,27 @@ int get_bool(const char *path, int defval, const char *name)
 	return defval;
 }
 
-/*
- * Function returns 64-bit unsigned integer value read from a text file. See
- * utils.h for details.
- */
 uint64_t get_uint64(const char *path, uint64_t defval, const char *name)
 {
 	char *p = get_text(path, name);
-	uint64_t retval = defval;
 
-	if (p) {
-		if (sscanf(p, "%" SCNx64, &defval) == 1)
-			retval = defval;
-		free(p);
-	}
-	return retval;
+	if (!p)
+		return defval;
+
+	str_toul(&defval, p, NULL, 16);
+	free(p);
+	return defval;
 }
 
-/*
- * Function returns integer value read from a text file.
- * See utils.h for details.
- */
 int get_int(const char *path, int defval, const char *name)
 {
 	char *p = get_text(path, name);
-	if (p) {
-		defval = strtol(p, NULL, 10);
-		free(p);
-	}
+
+	if (!p)
+		return defval;
+
+	str_toi(&defval, p, NULL, 10);
+	free(p);
 	return defval;
 }
 
@@ -181,11 +175,13 @@ ssize_t buf_write(const char *path, const char *buf)
 
 	if (path == NULL)
 		__set_errno_and_return(EINVAL);
-	if ((buf == NULL) || (strlen(buf) == 0))
+
+	if (buf == NULL || strnlen(buf, WRITE_BUFFER_SIZE) == 0)
 		__set_errno_and_return(ENODATA);
+
 	fd = open(path, O_WRONLY);
 	if (fd >= 0) {
-		size = write(fd, buf, strlen(buf));
+		size = write(fd, buf, strnlen(buf, WRITE_BUFFER_SIZE));
 		close(fd);
 	}
 	return size;
@@ -235,8 +231,8 @@ void get_id(const char *path, struct device_id *did)
 			t = strchr(p, ':');
 			if (t) {
 				*(t++) = '\0';
-				did->major = strtol(p, NULL, 10);
-				did->minor = strtol(t, NULL, 10);
+				str_toi(&did->major, p, NULL, 10);
+				str_toi(&did->minor, t, NULL, 10);
 			}
 			free(p);
 		}
@@ -359,6 +355,71 @@ char *str_dup(const char *src)
 	return ret;
 }
 
+static int _str_to_num(const char *strptr, char **endptr, int base, unsigned long *n, int is_signed)
+{
+	char *c;
+	int sign_occured = 0;
+
+	assert(n);
+	if (!strptr)
+		return 1;
+	errno = 0;
+	if (is_signed)
+		*n = (unsigned long)strtol(strptr, &c, base);
+	else {
+		while ((*strptr == '-' || *strptr == '+' || isspace(*strptr)) &&
+				*strptr != '\0' && !sign_occured) {
+			if (*strptr == '-' || *strptr == '+')
+				sign_occured = 1;
+			strptr++;
+		}
+		*n = strtoul(strptr, &c, base);
+	}
+	if (errno != 0 || strptr == c)
+		return 1;
+	if (endptr)
+		*endptr = c;
+	return 0;
+}
+
+static int _str_to_num_signed(const char *strptr, char **endptr, int base, unsigned long *n)
+{
+	return _str_to_num(strptr, endptr, base, n, 1);
+}
+
+static int _str_to_num_unsigned(const char *strptr, char **endptr, int base, unsigned long *n)
+{
+	return _str_to_num(strptr, endptr, base, n, 0);
+}
+
+static inline int value_in_range_signed(long value, long min, long max)
+{
+	return (value >= min && value <= max);
+}
+
+static inline int value_in_range_unsigned(unsigned long value, unsigned long min, unsigned long max)
+{
+	return (value >= min && value <= max);
+}
+
+#define _DECL_STR_TO_NUM(name, sign, type, min, max) \
+int name(sign type * dest, const char *strptr, char **endptr, int base) \
+{ \
+	unsigned long n; \
+	if ((!dest && !endptr) || _str_to_num_##sign(strptr, endptr, base, &n)) \
+		return 1; \
+	if (!value_in_range_##sign(n, min, max)) \
+		return 1; \
+	if (dest)\
+		*dest = (sign type)n; \
+	return 0; \
+}
+
+_DECL_STR_TO_NUM(str_tol, signed, long, LONG_MIN, LONG_MAX)
+_DECL_STR_TO_NUM(str_toul, unsigned, long, 0, ULONG_MAX)
+_DECL_STR_TO_NUM(str_toi, signed, int, INT_MIN, INT_MAX)
+_DECL_STR_TO_NUM(str_toui, unsigned, int, 0, UINT_MAX)
+
 char *get_path_hostN(const char *path)
 {
 	char *c = NULL, *s = NULL, *p = str_dup(path);
diff --git a/src/utils.h b/src/utils.h
index cfd6855..3f5a77f 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -307,6 +307,71 @@ char *str_cpy(char *dest, const char *src, size_t size);
  */
 char *str_dup(const char *src);
 
+/**
+ * @brief Converts string to long integer.
+ *
+ * This function works similar to strtol.
+ * Writes to destination only if successfully read the number.
+ * Destination can be NULL if endptr is set.
+ *
+ * @param[in]      dest            Pointer to destination.
+ * @param[in]      strptr          Pointer to source string.
+ * @param[in]      endptr          Pointer to the next character in string after parsed value.
+ * @param[in]      base            Base of the numerical value in string.
+ *
+ * @return 0 if operation was successful, otherwise 1.
+ */
+int str_tol(signed long *dest, const char *strptr, char **endptr, int base);
+
+/**
+ * @brief Converts string to unsigned long integer.
+ *
+ * This function works similar to strtoul. Skips + and - characters.
+ * Writes to destination only if successfully read the number.
+ * Destination can be NULL if endptr is set.
+ *
+ * @param[in]      dest            Pointer to destination.
+ * @param[in]      strptr          Pointer to source string.
+ * @param[in]      endptr          Pointer to the next character in string after parsed value.
+ * @param[in]      base            Base of the numerical value in string.
+ *
+ * @return 0 if operation was successful, otherwise 1.
+ */
+int str_toul(unsigned long *dest, const char *strptr, char **endptr, int base);
+
+/**
+ * @brief Converts string to integer.
+ *
+ * This function works similar to strtol, but for int.
+ * Writes to destination only if successfully read the number.
+ * Destination can be NULL if endptr is set.
+ *
+ * @param[in]      dest            Pointer to destination.
+ * @param[in]      strptr          Pointer to source string.
+ * @param[in]      endptr          Pointer to the next character in string after parsed value.
+ * @param[in]      base            Base of the numerical value in string.
+ *
+ * @return 0 if operation was successful, otherwise 1.
+ */
+int str_toi(signed int *dest, const char *strptr, char **endptr, int base);
+
+/**
+ * @brief Converts string to unsigned integer.
+ *
+ * This function works similar to strtoul, but for unsigned int.
+ * Skips + and - characters.
+ * Writes to destination only if successfully read the number.
+ * Destination can be NULL if endptr is set.
+ *
+ * @param[in]      dest            Pointer to destination.
+ * @param[in]      strptr          Pointer to source string.
+ * @param[in]      endptr          Pointer to the next character in string after parsed value.
+ * @param[in]      base            Base of the numerical value in string.
+ *
+ * @return 0 if operation was successful, otherwise 1.
+ */
+int str_toui(unsigned int *dest, const char *strptr, char **endptr, int base);
+
 /**
  */
 char *truncate_path_component_rev(const char *path, int index);
diff --git a/src/vmdssd.c b/src/vmdssd.c
index d4d3d28..3c6d24b 100644
--- a/src/vmdssd.c
+++ b/src/vmdssd.c
@@ -151,7 +151,7 @@ int vmdssd_write(struct block_device *device, enum ibpi_pattern ibpi)
 	get_ctrl(ibpi, &val);
 	snprintf(buf, WRITE_BUFFER_SIZE, "%u", val);
 	snprintf(attention_path, PATH_MAX, "%s/attention", slot->sysfs_path);
-	if (buf_write(attention_path, buf) != (ssize_t) strlen(buf)) {
+	if (buf_write(attention_path, buf) != (ssize_t) strnlen(buf, WRITE_BUFFER_SIZE)) {
 		log_error("%s write error: %d\n", slot->sysfs_path, errno);
 		return -1;
 	}

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/debug/.build-id/32/576a97458b6d46e6f8216e47768657988a8ed8.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/8f/a061ab00a6546b06516455fc594c9b5bdad8f4.debug

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/debug/.build-id/24/a477bf1f8b602ae24518d7a656e5ca5d3c709b.debug
-rw-r--r--  root/root   /usr/lib/debug/.build-id/aa/9a8a24be6eba3657958efddb4013e566958512.debug

No differences were encountered between the control files of package ledmon

Control files of package ledmon-dbgsym: lines which differ (wdiff format)

  • Build-Ids: 24a477bf1f8b602ae24518d7a656e5ca5d3c709b aa9a8a24be6eba3657958efddb4013e566958512 32576a97458b6d46e6f8216e47768657988a8ed8 8fa061ab00a6546b06516455fc594c9b5bdad8f4

More details

Full run details