From db05675f38d85b8c3d3967eb4ed26a8edfd2580b Mon Sep 17 00:00:00 2001 From: "Liu, Xinwu" Date: Tue, 17 Jul 2018 15:34:28 +0800 Subject: [PATCH] tools: acrn-crashlog: New apis to replace losetup and fdisk This patch adds new apis to replace commands losetup and fdisk. Main changes include: 1. impletement apis to operate loop devices directly. 2. impletement apis to get partition information from image file. Signed-off-by: Liu, Xinwu Acked-by: Chen Gang --- tools/acrn-crashlog/acrnprobe/Makefile | 5 +- tools/acrn-crashlog/acrnprobe/loop.c | 232 +++++++++++++++++++++++++ 2 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 tools/acrn-crashlog/acrnprobe/loop.c diff --git a/tools/acrn-crashlog/acrnprobe/Makefile b/tools/acrn-crashlog/acrnprobe/Makefile index 85a8dea95..5cafc299a 100644 --- a/tools/acrn-crashlog/acrnprobe/Makefile +++ b/tools/acrn-crashlog/acrnprobe/Makefile @@ -3,7 +3,7 @@ MINOR_VERSION=0 VERSION_H = $(BUILDDIR)/include/acrnprobe/version.h -LIBS = -lpthread -lxml2 -lcrypto -lrt $(EXTRA_LIBS) +LIBS = -lpthread -lxml2 -lcrypto -lrt -lblkid $(EXTRA_LIBS) INCLUDE += -I $(CURDIR)/include -I /usr/include/libxml2 INCLUDE += -I $(BUILDDIR)/include/acrnprobe CFLAGS += $(INCLUDE) @@ -36,7 +36,8 @@ $(BUILDDIR)/acrnprobe/bin/acrnprobe: $(BUILDDIR)/acrnprobe/obj/main.o \ $(BUILDDIR)/acrnprobe/obj/property.o \ $(BUILDDIR)/acrnprobe/obj/probeutils.o \ $(BUILDDIR)/acrnprobe/obj/history.o \ - $(BUILDDIR)/acrnprobe/obj/android_events.o + $(BUILDDIR)/acrnprobe/obj/android_events.o \ + $(BUILDDIR)/acrnprobe/obj/loop.o $(CC) -o $@ $^ $(LDFLAGS) .PHONY: clean diff --git a/tools/acrn-crashlog/acrnprobe/loop.c b/tools/acrn-crashlog/acrnprobe/loop.c new file mode 100644 index 000000000..3aa899732 --- /dev/null +++ b/tools/acrn-crashlog/acrnprobe/loop.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2018 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "log_sys.h" + +#define DEV_LOOP_CTL "/dev/loop-control" + +static int get_par_startaddr_from_img(const char *img, + const char *target_parname, + unsigned long long *start) +{ + blkid_probe pr; + blkid_partlist ls; + blkid_partition par; + int i; + int nparts; + const char *par_name; + unsigned int sector_size; + unsigned long long par_start; + + if (!img || !target_parname || !start) + return -1; + + pr = blkid_new_probe_from_filename(img); + if (!pr) { + LOGE("blkid new probe failed\n"); + return -1; + } + ls = blkid_probe_get_partitions(pr); + if (!ls) { + LOGE("blkid get partitions failed\n"); + goto err; + } + nparts = blkid_partlist_numof_partitions(ls); + if (nparts <= 0) { + LOGE("(%d) partitions in (%s)??\n", nparts, img); + goto err; + } + + for (i = 0; i < nparts; i++) { + par = blkid_partlist_get_partition(ls, i); + par_name = blkid_partition_get_name(par); + if (!par_name) { + LOGW("A partition in (%s) don't have name??\n", img); + continue; + } + if (!strcmp(par_name, target_parname)) + goto found; + } + LOGE("no partition of (%s) is named %s\n", img, target_parname); +err: + blkid_free_probe(pr); + return -1; +found: + sector_size = blkid_probe_get_sectorsize(pr); + par_start = (unsigned long long)blkid_partition_get_start(par); + *start = par_start * sector_size; + blkid_free_probe(pr); + return 0; +} + +int loopdev_num_get_free(void) +{ + int loopctlfd; + int devnr; + + loopctlfd = open(DEV_LOOP_CTL, O_RDONLY); + if (loopctlfd == -1) { + LOGE("failed to open %s, error (%s)\n", DEV_LOOP_CTL, + strerror(errno)); + return -errno; + } + + devnr = ioctl(loopctlfd, LOOP_CTL_GET_FREE); + if (devnr == -1) { + LOGE("failed to get free loopdev, error (%s)\n", + strerror(errno)); + close(loopctlfd); + return -errno; + } + + close(loopctlfd); + return devnr; +} + +static int loopdev_set_status(const char *loopdev, + const struct loop_info64 *info) +{ + int loopfd; + int res; + + if (!loopdev || !info) + return -EINVAL; + + loopfd = open(loopdev, O_RDWR); + if (loopfd == -1) { + LOGE("failed to open (%s), error(%s)\n", loopdev, + strerror(errno)); + return -errno; + } + + res = ioctl(loopfd, LOOP_SET_STATUS64, info); + if (res == -1) { + LOGE("failed to set info to (%s), error(%s)\n", loopdev, + strerror(errno)); + close(loopfd); + return -errno; + } + + close(loopfd); + return 0; +} + +static int loopdev_set_img(const char *loopdev, const char *img_path) +{ + int loopfd; + int imgfd; + int res; + + if (!loopdev || !img_path) + return -EINVAL; + + loopfd = open(loopdev, O_WRONLY); + if (loopfd == -1) { + LOGE("failed to open %s, error (%s)\n", loopdev, + strerror(errno)); + return -errno; + } + + imgfd = open(img_path, O_RDONLY); + if (imgfd == -1) { + LOGE("failed to open %s, error (%s)\n", img_path, + strerror(errno)); + close(loopfd); + return -errno; + } + + res = ioctl(loopfd, LOOP_SET_FD, imgfd); + if (res == -1) { + LOGE("failed to set (%s) to (%s), error (%s)\n", img_path, + loopdev, strerror(errno)); + close(loopfd); + close(imgfd); + return -errno; + } + + close(loopfd); + close(imgfd); + return 0; +} + +int loopdev_set_img_par(const char *loopdev, const char *img_path, + const char *parname) +{ + struct loop_info64 info; + unsigned long long par_start; + int res; + + if (!loopdev || !img_path || !parname) + return -1; + + res = get_par_startaddr_from_img(img_path, parname, &par_start); + if (res == -1) { + LOGE("failed to get data par startaddr\n"); + return -1; + } + + res = loopdev_set_img(loopdev, img_path); + if (res) { + LOGE("failed to set img (%s) to (%s), error (%s)\n", + img_path, loopdev, strerror(-res)); + return -1; + } + + memset(&info, 0, sizeof(info)); + info.lo_offset = par_start; + + res = loopdev_set_status(loopdev, &info); + if (res < 0) { + LOGE("failed to set loopdev, error (%s)\n", strerror(-res)); + return -1; + } + return 0; +} + +int loopdev_check_parname(const char *loopdev, const char *parname) +{ + struct ext2_super_block super; + int fd; + const int skiprate = 512; + loff_t sk = 0; + + if (!loopdev || !parname) + return -ENOENT; + + /* quickly find super block */ + fd = open(loopdev, O_RDONLY); + if (fd == -1) { + LOGE("failed to open (%s), error(%s)\n", loopdev, + strerror(errno)); + return -errno; + } + for (; lseek64(fd, sk, SEEK_SET) != -1 && + read(fd, &super, 512) == 512; sk += skiprate) { + if (super.s_magic != EXT2_SUPER_MAGIC) + continue; + + LOGD("find super block at +%ld\n", sk); + /* only look into the primary super block */ + if (super.s_volume_name[0]) { + close(fd); + return !strcmp(super.s_volume_name, parname); + } + break; + } + + close(fd); + return 0; +}