mirror of
https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
synced 2024-11-23 01:53:47 +08:00
misc/mk_hugefiles: simplify get_partition_start()
search_sysfs_block() is causing -Wformat-truncation warnings. These could be fixed by checking the return value of snprintf(), instead of doing buggy checks like 'strlen(p_de->d_name) > SYSFS_PATH_LEN - strlen(path) - 32', which has an integer underflow bug. However, the only purpose of search_sysfs_block() is to find the sysfs directory for a block device by device number. That can trivially be done using /sys/dev/block/$major:$minor. So just do that instead. Also make get_partition_start() explicitly Linux-only, as it has never worked anywhere else. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
44ee1fb80b
commit
4d890149b9
@ -1,11 +1,5 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Fall back to Linux's definitions of makedev and major are needed.
|
||||
* The search_sysfs_block() function is highly unlikely to work on
|
||||
* non-Linux systems anyway.
|
||||
*/
|
||||
#ifndef makedev
|
||||
#define makedev(maj, min) (((maj) << 8) + (min))
|
||||
#endif
|
||||
#endif
|
||||
|
@ -2,13 +2,8 @@
|
||||
* mk_hugefiles.c -- create huge files
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX in Solaris */
|
||||
#define _BSD_SOURCE /* for makedev() and major() */
|
||||
#define _DEFAULT_SOURCE /* since glibc 2.20 _BSD_SOURCE is deprecated */
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <fcntl.h>
|
||||
@ -68,141 +63,30 @@ static char *fn_buf;
|
||||
static char *fn_numbuf;
|
||||
int zero_hugefile = 1;
|
||||
|
||||
#define SYSFS_PATH_LEN 300
|
||||
typedef char sysfs_path_t[SYSFS_PATH_LEN];
|
||||
|
||||
#ifndef HAVE_SNPRINTF
|
||||
/*
|
||||
* We are very careful to avoid needing to worry about buffer
|
||||
* overflows, so we don't really need to use snprintf() except as an
|
||||
* additional safety check. So if snprintf() is not present, it's
|
||||
* safe to fall back to vsprintf(). This provides portability since
|
||||
* vsprintf() is guaranteed by C89, while snprintf() is only
|
||||
* guaranteed by C99 --- which for example, Microsoft Visual Studio
|
||||
* has *still* not bothered to implement. :-/ (Not that I expect
|
||||
* mke2fs to be ported to MS Visual Studio any time soon, but
|
||||
* libext2fs *does* get built on Microsoft platforms, and we might
|
||||
* want to move this into libext2fs some day.)
|
||||
*/
|
||||
static int my_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = vsprintf(str, format, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define snprintf my_snprintf
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fall back to Linux's definitions of makedev and major are needed.
|
||||
* The search_sysfs_block() function is highly unlikely to work on
|
||||
* non-Linux systems anyway.
|
||||
*/
|
||||
#ifndef makedev
|
||||
#define makedev(maj, min) (((maj) << 8) + (min))
|
||||
#endif
|
||||
|
||||
static char *search_sysfs_block(dev_t devno, sysfs_path_t ret_path)
|
||||
{
|
||||
struct dirent *de, *p_de;
|
||||
DIR *dir = NULL, *p_dir = NULL;
|
||||
FILE *f;
|
||||
sysfs_path_t path, p_path;
|
||||
unsigned int major, minor;
|
||||
char *ret = ret_path;
|
||||
|
||||
ret_path[0] = 0;
|
||||
if ((dir = opendir("/sys/block")) == NULL)
|
||||
return NULL;
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
|
||||
strlen(de->d_name) > sizeof(path)-32)
|
||||
continue;
|
||||
snprintf(path, SYSFS_PATH_LEN,
|
||||
"/sys/block/%s/dev", de->d_name);
|
||||
f = fopen(path, "r");
|
||||
if (f &&
|
||||
(fscanf(f, "%u:%u", &major, &minor) == 2)) {
|
||||
fclose(f); f = NULL;
|
||||
if (makedev(major, minor) == devno) {
|
||||
snprintf(ret_path, SYSFS_PATH_LEN,
|
||||
"/sys/block/%s", de->d_name);
|
||||
goto success;
|
||||
}
|
||||
#ifdef major
|
||||
if (major(devno) != major)
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
if (f)
|
||||
fclose(f);
|
||||
|
||||
snprintf(path, SYSFS_PATH_LEN, "/sys/block/%s", de->d_name);
|
||||
|
||||
if (p_dir)
|
||||
closedir(p_dir);
|
||||
if ((p_dir = opendir(path)) == NULL)
|
||||
continue;
|
||||
while ((p_de = readdir(p_dir)) != NULL) {
|
||||
if (!strcmp(p_de->d_name, ".") ||
|
||||
!strcmp(p_de->d_name, "..") ||
|
||||
(strlen(p_de->d_name) >
|
||||
SYSFS_PATH_LEN - strlen(path) - 32))
|
||||
continue;
|
||||
snprintf(p_path, SYSFS_PATH_LEN, "%s/%s/dev",
|
||||
path, p_de->d_name);
|
||||
|
||||
f = fopen(p_path, "r");
|
||||
if (f &&
|
||||
(fscanf(f, "%u:%u", &major, &minor) == 2) &&
|
||||
(((major << 8) + minor) == devno)) {
|
||||
fclose(f);
|
||||
snprintf(ret_path, SYSFS_PATH_LEN, "%s/%s",
|
||||
path, p_de->d_name);
|
||||
goto success;
|
||||
}
|
||||
if (f)
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
ret = NULL;
|
||||
success:
|
||||
if (dir)
|
||||
closedir(dir);
|
||||
if (p_dir)
|
||||
closedir(p_dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static blk64_t get_partition_start(const char *device_name)
|
||||
static blk64_t
|
||||
get_partition_start(const char *device_name EXT2FS_ATTR((unused)))
|
||||
{
|
||||
#ifdef __linux__
|
||||
unsigned long long start;
|
||||
sysfs_path_t path;
|
||||
char path[128];
|
||||
struct stat st;
|
||||
FILE *f;
|
||||
char *cp;
|
||||
int n;
|
||||
|
||||
if ((stat(device_name, &st) < 0) || !S_ISBLK(st.st_mode))
|
||||
return 0;
|
||||
|
||||
cp = search_sysfs_block(st.st_rdev, path);
|
||||
if (!cp)
|
||||
return 0;
|
||||
if (strlen(path) > SYSFS_PATH_LEN - sizeof("/start"))
|
||||
return 0;
|
||||
strcat(path, "/start");
|
||||
sprintf(path, "/sys/dev/block/%d:%d/start",
|
||||
major(st.st_rdev), minor(st.st_rdev));
|
||||
f = fopen(path, "r");
|
||||
if (!f)
|
||||
return 0;
|
||||
n = fscanf(f, "%llu", &start);
|
||||
fclose(f);
|
||||
return (n == 1) ? start : 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static errcode_t create_directory(ext2_filsys fs, char *dir,
|
||||
|
Loading…
Reference in New Issue
Block a user