feat(libfs): parse disk offset

This commit is contained in:
d0p1 🏳️‍⚧️ 2024-09-16 14:54:31 +02:00
parent 560a5000da
commit 31976c4c9f
8 changed files with 138 additions and 3 deletions

View file

@ -32,6 +32,8 @@ AC_CHECK_INCLUDES_DEFAULT
AC_C_CONST
AC_C_INLINE
AC_CHECK_FUNCS_ONCE(strtoull)
AC_CHECK_HEADERS(m4_normalize([
libgen.h
getopt.h
@ -52,6 +54,7 @@ AC_CONFIG_FILES([Makefile
liblzp/Makefile
liblzp/tests/Makefile
libfs/Makefile
libfs/tests/Makefile
tools/Makefile
linux/Makefile
fuse/Makefile])

View file

@ -1,3 +1,5 @@
SUBDIRS = tests
AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)
noinst_LIBRARIES = libfs.a
libfs_a_SOURCES = bio/raw.c bio/bio.c balloc.c dir.c inode.c rw.c super.c
libfs_a_SOURCES = bio/raw.c bio/bio.c balloc.c dir.c inode.c rw.c super.c offset.c

60
libfs/offset.c Normal file
View file

@ -0,0 +1,60 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
/*
* S = sectors (512)
* K = kilobytes
* M = Megabytes
* G = Gigabytes
* T = Terabytes
*/
static const struct {
char unit;
uint64_t mult;
} units[] = {
{'S', 512},
{'K', 1000},
{'M', 1000000},
{'G', 1000000000},
{'T', 1000000000000},
{0, 0}
};
uint64_t fs_str2offset(const char *str)
{
char u;
uint64_t mult;
uint64_t off;
int idx;
if (str == NULL)
{
return (0);
}
/* default to sectors */
mult = units[0].mult;
u = str[strlen(str) - 1];
for (idx = 0; units[idx].unit != 0; idx++)
{
if (u == units[idx].unit)
{
mult = units[idx].mult;
break;
}
}
#ifdef HAVE_STRTOULL
off = strtoull(str, NULL, 0);
#else
off = strtoul(str, NULL, 0);
#endif /* HAVE_STRTOULL */
return (off * mult);
}

View file

@ -1,11 +1,14 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stupidfs.h>
#include "super.h"
#include "bio/bio.h"
uint64_t fs_str2offset(const char *str);
int
fs_super_valide(struct stpdfs_sb *sb)
{
@ -36,12 +39,20 @@ fs_super_valide(struct stpdfs_sb *sb)
return (0);
}
/**
* \param super
* \param fname
*/
int
fs_super_open(struct fs_super *super, const char *fname)
{
struct fs_buffer *buff;
char *ptr;
ptr = (char *)fname;
#ifdef _WIN32
super->fd = open(fname, O_RDWR | O_BINARY);
super->fd = open(strtok(ptr, "@@"), O_RDWR | O_BINARY);
#else
super->fd = open(fname, O_RDWR);
#endif
@ -51,6 +62,8 @@ fs_super_open(struct fs_super *super, const char *fname)
return (-1);
}
super->offset = fs_str2offset(strtok(NULL, "@@"));
buff = fs_bio_bread(super->fd, STPDFS_SB_BLOCK);
if (!buff) goto err;

View file

@ -6,6 +6,7 @@
struct fs_super {
int fd;
uint64_t offset;
struct stpdfs_sb sb;
};

7
libfs/tests/Makefile.am Normal file
View file

@ -0,0 +1,7 @@
TESTS = test_offset
check_PROGRAMS = test_offset
AM_CFLAGS = -I../
LDADD = -lcmocka ../libfs.a
test_offset_SOURCES = test_offset.c

43
libfs/tests/test_offset.c Normal file
View file

@ -0,0 +1,43 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>
int64_t fs_str2offset(const char *str);
static void
test_default(void **state)
{
assert_int_equal(0, fs_str2offset(NULL));
assert_int_equal(512, fs_str2offset("1"));
}
static void
test_valid_units(void **state)
{
assert_int_equal(1024, fs_str2offset("2S"));
assert_int_equal(2000, fs_str2offset("2K"));
assert_int_equal(4000000, fs_str2offset("4M"));
assert_int_equal(8000000000, fs_str2offset("8G"));
assert_int_equal(3000000000000, fs_str2offset("3T"));
}
static void
test_invalid_units(void **state)
{
assert_int_equal(2048, fs_str2offset("4D"));
assert_int_equal(5120, fs_str2offset("10H"));
}
int
main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_default),
cmocka_unit_test(test_valid_units),
cmocka_unit_test(test_invalid_units),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

View file

@ -161,7 +161,13 @@ usage(int retval)
}
else
{
printf("Usage %s: [options] /dev/name\n\n", prg_name);
printf("Usage %s: [OPTIONS]... /dev/name\n\n", prg_name);
printf("Options:\n");
printf(" -i, --inode <inum> inspect inode\n.");
printf(" -b, --block <bnum> inspect block\n");
printf(" -s, --super inspect superblock\n");
printf(" -h, --help display this menu\n");
printf(" -V, --version display version information\n");
}
exit(retval);