From 1e3f4487381cbd792cad3a0956d32de1ce02b43b Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Wed, 3 Apr 2024 11:40:53 +0200 Subject: [PATCH] Add 'osu --resize' command to support resizing of the rootfs partition. resize2fs is disabled in initrd to not modify the flashed image during system boot, so that delta file can be applied during OS Upgrade. However additional software may need to be installed during development, so the ability to perfrom resize is added. To resize, the rootfs partition must be mounted as RW: mount -o rw,remount / osu --resize Change-Id: I74914464295629db5e8e2b696f41e1eb7a316b02 --- tools/osu/CMakeLists.txt | 4 +- tools/osu/osu.c | 109 ++++++++++++++++++++++++++- tools/osu/resize.c | 156 +++++++++++++++++++++++++++++++++++++++ tools/osu/resize.h | 19 +++++ 4 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 tools/osu/resize.c create mode 100644 tools/osu/resize.h diff --git a/tools/osu/CMakeLists.txt b/tools/osu/CMakeLists.txt index b9a8360..a1e6628 100644 --- a/tools/osu/CMakeLists.txt +++ b/tools/osu/CMakeLists.txt @@ -2,9 +2,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) SET(OUTPUT_BIN_NAME osu) PROJECT(update-control-tools-${OUTPUT_BIN_NAME} C) -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(. ${CMAKE_SOURCE_DIR}/include) -FILE(GLOB_RECURSE SRCS osu.c) +FILE(GLOB_RECURSE SRCS osu.c resize.c) ADD_EXECUTABLE(${OUTPUT_BIN_NAME} ${SRCS}) SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") TARGET_LINK_LIBRARIES(${OUTPUT_BIN_NAME} ${REQUIRED_PKGS_LDFLAGS} update-control) diff --git a/tools/osu/osu.c b/tools/osu/osu.c index d4158db..744ba47 100644 --- a/tools/osu/osu.c +++ b/tools/osu/osu.c @@ -1,11 +1,98 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * OSU is a tool to support Tizen OS Upgrade testing and development + * + */ + #include +#include +#include +#include #include "update_control.h" +#include "resize.h" -int main(int argc, char **argv) + +struct arguments { + bool resize; + bool update; +}; + +static void print_help(char*); + +static int parse_args(int argc, char **argv, struct arguments *args) { - int ret = 0; + assert(argv); + assert(args); + + args->resize = false; + args->update = true; + + struct option long_options[] = { + {"resize", no_argument, NULL, 'r'}, + {"update", no_argument, NULL, 'u'}, + {"help", no_argument, NULL, 'h'}, + {} + }; + + int opt; + while ((opt = getopt_long_only(argc, argv, "rh", long_options, NULL)) !=-1) { + args->update = false; + + switch (opt) { + case 'r': { + args->resize = true; + return 0; + } + case 'u': { + args->update = true; + return 0; + } + case 'h': { + print_help(argv[0]); + return 0; + } + case '?': { + print_help(argv[0]); + return 1; + } + } + } + + return 0; +} + +static void print_help(char *my_name) +{ + assert(my_name); + printf("Usage:\n" + " %s [--resize|--update]\n\n" + "Possible arguments:\n" + " --help Print this help\n" + " --update Trigger the OS Upgrade\n" + " --resize Run resize2fs on the rootfs partition.\n" + " After that, performing the OS Upgrade will be impossible.\n\n" + "By default, without an argument, the OS Upgrade will be triggered.\n\n", my_name); +} + +static int do_update() +{ + int ret = 0; ret = update_control_initialize(); if (ret != UPDATE_CONTROL_ERROR_NONE) { printf("Failed to initialize: %d\n", ret); @@ -41,3 +128,21 @@ cleanup: return ret; } + +int main(int argc, char **argv) +{ + int ret = 0; + struct arguments args; + + if (parse_args(argc, argv, &args) != 0) { + return 1; + } + + if (args.resize) { + ret = do_resize(); + } else if (args.update) { + ret = do_update(); + } + + return ret; +} diff --git a/tools/osu/resize.c b/tools/osu/resize.c new file mode 100644 index 0000000..3462b76 --- /dev/null +++ b/tools/osu/resize.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LINE_SIZE 1000 + +static bool check_readonly(char *flags) +{ + assert(flags); + char *saveptr = NULL; + char *token = strtok_r(flags, ",", &saveptr); + + while (token != NULL) { + if (strncmp(token, "ro", 3) == 0) { + return true; + } + token = strtok_r(NULL, ",", &saveptr); + } + + return false; +} + +static char *get_dev_name(const char *device_mount_point) +{ + FILE *file = fopen("/proc/mounts", "r"); + if (file == NULL) { + fprintf(stderr,"/proc/mounts open error (%d): %m\n", errno); + return NULL; + } + + char line[MAX_LINE_SIZE]; + char *dev_name = NULL; + + while ((fgets(line, MAX_LINE_SIZE, file)) != NULL) { + char *saveptr = NULL; + + char *dev_name_candidate = strtok_r(line, " ", &saveptr); + char *mount_point = strtok_r(NULL, " ", &saveptr); + strtok_r(NULL, " ", &saveptr); // skip FS type + char *flags = strtok_r(NULL, " ", &saveptr); + + if (dev_name_candidate == NULL || mount_point == NULL || flags == NULL) { + fprintf(stderr, "/proc/mounts parsing error\n"); + goto out; + } + + if (strncmp(mount_point, device_mount_point, strlen(device_mount_point)+1) == 0) { + if (check_readonly(flags)) { + fprintf(stderr, "The device %s is mounted as read-only. Please, remount" + " the filesystem as RW and try again:\n mount -o rw,remount %s\n", + dev_name_candidate, device_mount_point); + goto out; + } + + dev_name = strdup(dev_name_candidate); + if (dev_name == NULL) { + fprintf(stderr,"Memory allocation error (%d): %m\n", errno); + goto out; + } + + break; + } + } + + if (dev_name == NULL) { + fprintf(stderr, "Not found rootfs in /proc/mounts\n"); + } + +out: + fclose(file); + return dev_name; +} + +static int run_resize(const char *dev_name) +{ + int ret = 0; + pid_t pid = fork(); + + if (pid == -1) { + fprintf(stderr, "fork() error: (%d) %m\n", errno); + return 1; + } + + if (pid == 0) { + execl("/sbin/resize2fs", "resize2fs", dev_name, NULL); + } else { + int r, status; + bool is_ok; + + do { + r = waitpid(pid, &status, 0); + is_ok = r >= 0; + } while (!is_ok && errno == EINTR); + + if (!is_ok) { + fprintf(stderr, "resize2fs on %s execution error: (%d) %m\n", dev_name, errno); + return 1; + } + + if (WIFEXITED(status)) + ret = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + ret = WTERMSIG(status); + else if (WIFSTOPPED(status)) + ret = WSTOPSIG(status); + } + return ret; +} + +static int resize_mount_point(const char *device_mount_point) +{ + int ret = 0; + printf("\nResizing %s\n", device_mount_point); + char *dev_name = get_dev_name(device_mount_point); + if (dev_name == NULL) + return 1; + + ret = run_resize(dev_name); + + free(dev_name); + return ret; +} + +int do_resize() +{ + int ret = 0; + ret = resize_mount_point("/"); + if (ret == 0) { + ret = resize_mount_point("/hal"); + } + return ret; +} diff --git a/tools/osu/resize.h b/tools/osu/resize.h new file mode 100644 index 0000000..8c9894d --- /dev/null +++ b/tools/osu/resize.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +int do_resize(); -- 2.34.1