diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/with-dev-root-do.c | 115 |
2 files changed, 120 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..d7e0452 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,5 @@ +INCLUDE(FindPkgConfig) +pkg_search_module(libudev REQUIRED libudev) +add_executable(with-dev-root-do with-dev-root-do.c) +target_link_libraries(with-dev-root-do ${libudev_LIBRARIES}) +install(PROGRAMS with-dev-root-do DESTINATION /bin) diff --git a/src/with-dev-root-do.c b/src/with-dev-root-do.c new file mode 100644 index 0000000..e822d00 --- /dev/null +++ b/src/with-dev-root-do.c @@ -0,0 +1,115 @@ +/* -*- c-basic-offset: 8 -*- */ +/* + * Query udev for the real name of the device currently mounted + * as root filesystem and use it as an argument for a command. + * + * Copyright (C) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Author: Ćukasz Stelmach <l.stelmach@samsung.com> + * + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include <libudev.h> +#include <stdlib.h> +#include <string.h> + +void usage() { + fprintf(stderr, "Usage:\n\n with-dev-root-do <cmdline>\n\n"); + fprintf(stderr, "Execute the cmdline with the real name of the device currently mounted\n"); + fprintf(stderr, "as root file-system appended at the end or substituted for '{}'. Examples\n"); + fprintf(stderr, "assuming /dev/sda1 holds root file-system:\n\n"); + fprintf(stderr, " with-dev-root-do /sbin/fsck\n\n"); + fprintf(stderr, "runs \"/sbin/fsck /dev/sda1\"\n\n"); + fprintf(stderr, " with-dev-root-do /sbin/e2image {} /tmp/root.e2img\n\n"); + fprintf(stderr, "runs \"/sbin/e2image /dev/sda1 /tmp/root.e2img\"\n"); +} + +const char* find_node() { + struct stat s; + struct udev* udev=NULL; + struct udev_device *udev_device = NULL; + const char* node=NULL; + + if(stat("/", &s) < 0) { + perror("stat"); + return NULL; + } + + if (s.st_dev == 0) + return NULL; + + udev=udev_new(); + if(udev==NULL) { + fprintf(stderr, "I don't remember.\n"); + return NULL; + } + + udev_device=udev_device_new_from_devnum(udev, 'b', s.st_dev); + if(udev_device==NULL) { + fprintf(stderr, "Where do we come from?\n"); + return NULL; + } + + node=udev_device_get_devnode(udev_device); + if(node==NULL) { + fprintf(stderr, "Where are we going to?\n"); + return NULL; + } + return node; +} + +int main(int argc, char* argv[]) { + const char** cmdline; + const char* node; + int i; + int placeholder_found=0; + + if(argc < 2) { + usage(); + fprintf(stderr, "\nI don't want to be alone.\n"); + exit(1); + } + + cmdline=malloc((1+argc) * sizeof(char*)); + if(cmdline==NULL) { + perror("malloc"); + exit(1); + } + memset((char*)cmdline, 0, (1+argc) * sizeof(char*)); + + if((node=find_node())==NULL) { + free(cmdline); + exit(1); + } + + for (i=0; i < argc && argv[i+1]; i++) { + if(strncmp("{}", argv[i+1], 3)==0) { + placeholder_found=1; + cmdline[i] = node; + } else + cmdline[i] = argv[i+1]; + } + + if (!placeholder_found) + cmdline[i]=node; + + execv(cmdline[0], (char**) cmdline); + return 1; +} |