mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Using util_path_sysfs always leaves 5 bytes of memory unfreed as the value for the sysfs mount point is stored in a static variable to avoid multiple queries of /proc/mount. $ valgrind ./util_path_example sysfs ==3629315== Memcheck, a memory error detector ==3629315== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==3629315== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==3629315== Command: ./util_path_example sysfs ==3629315== Path for cpu: "/sys/devices/system/cpu" Path for memory: "/sys/devices/system/memory" ==3629315== ==3629315== HEAP SUMMARY: ==3629315== in use at exit: 5 bytes in 1 blocks ==3629315== total heap usage: 22 allocs, 21 frees, 18,435 bytes allocated ==3629315== ==3629315== LEAK SUMMARY: ==3629315== definitely lost: 0 bytes in 0 blocks ==3629315== indirectly lost: 0 bytes in 0 blocks ==3629315== possibly lost: 0 bytes in 0 blocks ==3629315== still reachable: 5 bytes in 1 blocks ==3629315== suppressed: 0 bytes in 0 blocks ==3629315== Rerun with --leak-check=full to see details of leaked memory ==3629315== ==3629315== For lists of detected and suppressed errors, rerun with: -s ==3629315== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) As per the Kernel rules for accessing sysfs information [1], searching for the sysfs mount point is a waste of time and systems that don't have sysfs mounted at /sys are considered broken. With those things in mind, util_path_sysfs() and especially sys_mount_point() can be simplified. sys_mount_point() will always return '/sys' unless the environment variable SYSFS_ROOT is set. With SYSFS_ROOT still being present, special container setups or test case scenarios are still possible but might need to be modified if they previously relied on util_path_sysfs() automatically finding the correct sysfs mount point. To make things more secure against malicious strings in SYSFS_ROOT, secure_getenv() is being used and the ordering of creating the formatted path string in util_path_sysfs() is changed slightly. Furthermore, the static variable is removed as no complicated query of the /proc fs is required anymore. Memory for the sysfs mount point value is properly freed now at the end of util_path_sysfs(). [1] https://www.kernel.org/doc/html/latest/admin-guide/sysfs-rules.html Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
260 lines
5.4 KiB
C
260 lines
5.4 KiB
C
/*
|
|
* util - Utility function library
|
|
*
|
|
* Work with paths
|
|
*
|
|
* Copyright IBM Corp. 2016, 2019
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#include <err.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include "lib/util_base.h"
|
|
#include "lib/util_libc.h"
|
|
#include "lib/util_path.h"
|
|
#include "lib/util_prg.h"
|
|
|
|
/*
|
|
* Verify that directory exists
|
|
*/
|
|
static void verify_dir(const char *dir)
|
|
{
|
|
struct stat sb;
|
|
int rc;
|
|
|
|
rc = stat(dir, &sb);
|
|
if (rc < 0)
|
|
err(EXIT_FAILURE, "Could not access directory: %s", dir);
|
|
if (!S_ISDIR(sb.st_mode))
|
|
errx(EXIT_FAILURE, "Is not a directory: %s", dir);
|
|
}
|
|
|
|
/*
|
|
* Return sysfs mount point
|
|
*
|
|
* The caller must free the memory for mount_point.
|
|
*/
|
|
static void sys_mount_point(char **mount_point)
|
|
{
|
|
char *dir;
|
|
|
|
/* Check the environment variable */
|
|
dir = secure_getenv("SYSFS_ROOT");
|
|
if (dir)
|
|
*mount_point = util_strdup(dir);
|
|
else
|
|
*mount_point = util_strdup("/sys");
|
|
verify_dir(*mount_point);
|
|
}
|
|
|
|
/**
|
|
* Construct a sysfs path
|
|
*
|
|
* The arguments of the function are used to specify a subdirectory under
|
|
* sysfs root.
|
|
*
|
|
* @param[in] fmt Format string for path
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns Allocated path
|
|
*/
|
|
char *util_path_sysfs(const char *fmt, ...)
|
|
{
|
|
char *path, *fmt_path, *sysfs;
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
util_vasprintf(&fmt_path, fmt, ap);
|
|
va_end(ap);
|
|
sys_mount_point(&sysfs);
|
|
/* Format and return full sysfs path */
|
|
util_asprintf(&path, "%s/%s", sysfs, fmt_path);
|
|
free(fmt_path);
|
|
free(sysfs);
|
|
|
|
return path;
|
|
}
|
|
|
|
/**
|
|
* Test if path exists and is readable
|
|
*
|
|
* This function has the same semantics as "-r path" in bash.
|
|
*
|
|
* @param[in] fmt Format string for path to test
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns true Path exists and is readable
|
|
* false Otherwise
|
|
*/
|
|
bool util_path_is_readable(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
char *path;
|
|
bool rc;
|
|
|
|
UTIL_VASPRINTF(&path, fmt, ap);
|
|
rc = access(path, R_OK) == 0;
|
|
free(path);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Test if path exists and is writable
|
|
*
|
|
* This function has the same semantics as "-w path" in bash.
|
|
*
|
|
* @param[in] fmt Format string for path to test
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns true Path exists and is writable
|
|
* false Otherwise
|
|
*/
|
|
bool util_path_is_writable(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
char *path;
|
|
bool rc;
|
|
|
|
UTIL_VASPRINTF(&path, fmt, ap);
|
|
rc = access(path, W_OK) == 0;
|
|
free(path);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Test if path exists and is a regular file
|
|
*
|
|
* This function has the same semantics as "-f path" in bash.
|
|
*
|
|
* @param[in] fmt Format string for path to test
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns true Path exists and is a regular file
|
|
* false Otherwise
|
|
*/
|
|
bool util_path_is_reg_file(const char *fmt, ...)
|
|
{
|
|
bool rc = false;
|
|
struct stat sb;
|
|
va_list ap;
|
|
char *path;
|
|
|
|
UTIL_VASPRINTF(&path, fmt, ap);
|
|
if (stat(path, &sb) == 0)
|
|
rc = S_ISREG(sb.st_mode);
|
|
free(path);
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Test if path exists and is a directory
|
|
*
|
|
* This function has the same semantics as "-d path" in bash.
|
|
*
|
|
* @param[in] fmt Format string for path to test
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns true Path exists and is a directory
|
|
* false Otherwise
|
|
*/
|
|
bool util_path_is_dir(const char *fmt, ...)
|
|
{
|
|
bool rc = false;
|
|
struct stat sb;
|
|
va_list ap;
|
|
char *path;
|
|
|
|
UTIL_VASPRINTF(&path, fmt, ap);
|
|
if (stat(path, &sb) == 0)
|
|
rc = S_ISDIR(sb.st_mode);
|
|
free(path);
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Test if path to directory or file exists
|
|
*
|
|
* This function has the same semantics as "-e path" in bash.
|
|
*
|
|
* @param[in] fmt Format string for path to test
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns true Path exists
|
|
* false Otherwise
|
|
*/
|
|
bool util_path_exists(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
char *path;
|
|
bool rc;
|
|
|
|
UTIL_VASPRINTF(&path, fmt, ap);
|
|
rc = access(path, F_OK) == 0;
|
|
free(path);
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Test if path exists, is a regular file, and permission is read-only
|
|
*
|
|
* @param[in] fmt Format string for path to test
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns true Path exists, is a regular file, and permission does
|
|
* not allow any write but allows read
|
|
* false Otherwise
|
|
*/
|
|
bool util_path_is_readonly_file(const char *fmt, ...)
|
|
{
|
|
bool rc = false;
|
|
struct stat sb;
|
|
va_list ap;
|
|
char *path;
|
|
|
|
UTIL_VASPRINTF(&path, fmt, ap);
|
|
if (stat(path, &sb) == 0) {
|
|
rc = S_ISREG(sb.st_mode) &&
|
|
(sb.st_mode & 0222) == 0 &&
|
|
(sb.st_mode & 0444) != 0;
|
|
}
|
|
free(path);
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Test if path exists, is a regular file, and permission is write-only
|
|
*
|
|
* @param[in] fmt Format string for path to test
|
|
* @param[in] ... Variable arguments for format string
|
|
*
|
|
* @returns true Path exists, is a regular file, and permission does
|
|
* not allow any read but allows write
|
|
* false Otherwise
|
|
*/
|
|
bool util_path_is_writeonly_file(const char *fmt, ...)
|
|
{
|
|
bool rc = false;
|
|
struct stat sb;
|
|
va_list ap;
|
|
char *path;
|
|
|
|
UTIL_VASPRINTF(&path, fmt, ap);
|
|
if (stat(path, &sb) == 0) {
|
|
rc = S_ISREG(sb.st_mode) &&
|
|
(sb.st_mode & 0222) != 0 &&
|
|
(sb.st_mode & 0444) == 0;
|
|
}
|
|
free(path);
|
|
return rc;
|
|
}
|
|
|