~vcs-imports/busybox/trunk

« back to all changes in this revision

Viewing changes to klibc-utils/resume.c

  • Committer: Denys Vlasenko
  • Date: 2017-08-18 17:15:29 UTC
  • Revision ID: git-v1:ab77e81a8527fa11a4f9392d97c2da037d6f4f98
klibc-utils: new applets: resume, nuke, minips

minips is a pure alias to ps, just in case someone needs 100% klibc-utils compat.
nuke is a primitive version of "rm -rf" without options and error checks. ~30 bytes.

resume is a tool for initramfs which resumes from a given block device.

function                                             old     new   delta
resume_main                                            -     582    +582
packed_usage                                       31640   31712     +72
nuke_main                                              -      28     +28
xstrtoull                                              -      24     +24
applet_names                                        2646    2665     +19
applet_main                                         1532    1544     +12
applet_suid                                           96      97      +1
applet_install_loc                                   192     193      +1
applet_flags                                          96      97      +1
------------------------------------------------------------------------------
(add/remove: 5/0 grow/shrink: 6/0 up/down: 740/0)             Total: 740 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2017 Denys Vlasenko <vda.linux@googlemail.com>
 
3
 *
 
4
 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
 
5
 */
 
6
//config:config RESUME
 
7
//config:       bool "resume"
 
8
//config:       default y
 
9
//config:       help
 
10
//config:       Resume from saved "suspend-to-disk" image
 
11
 
 
12
//applet:IF_RESUME(APPLET_NOEXEC(resume, resume, BB_DIR_BIN, BB_SUID_DROP, resume))
 
13
 
 
14
//kbuild:lib-$(CONFIG_RESUME) += resume.o
 
15
 
 
16
#include "libbb.h"
 
17
 
 
18
/* This is a NOEXEC applet. Be very careful! */
 
19
 
 
20
/* name_to_dev_t() in klibc-utils supports extended device name formats,
 
21
 * apart from the usual case where /dev/NAME already exists.
 
22
 *
 
23
 * - device number in hexadecimal represents itself (in dev_t layout).
 
24
 * - device number in major:minor decimal represents itself.
 
25
 * - if block device (or partition) with this name is found in sysfs.
 
26
 * - if /dev/ prefix is not given, it is assumed.
 
27
 *
 
28
 * klibc-utils also recognizes these, but they don't work
 
29
 * for "resume" tool purposes (thus we don't support them (yet?)):
 
30
 * - /dev/nfs
 
31
 * - /dev/ram (alias to /dev/ram0)
 
32
 * - /dev/mtd
 
33
 */
 
34
static dev_t name_to_dev_t(const char *devname)
 
35
{
 
36
        char devfile[sizeof(int)*3 * 2 + 4];
 
37
        char *sysname;
 
38
        unsigned major_num, minor_num;
 
39
        struct stat st;
 
40
        int r;
 
41
 
 
42
        if (strncmp(devname, "/dev/", 5) != 0) {
 
43
                char *cptr;
 
44
 
 
45
                cptr = strchr(devname, ':');
 
46
                if (cptr) {
 
47
                        /* Colon-separated decimal device number? */
 
48
                        *cptr = '\0';
 
49
                        major_num = bb_strtou(devname, NULL, 10);
 
50
                        if (!errno)
 
51
                                minor_num = bb_strtou(cptr + 1, NULL, 10);
 
52
                        *cptr = ':';
 
53
                        if (!errno)
 
54
                                return makedev(major_num, minor_num);
 
55
                } else {
 
56
                        /* Hexadecimal device number? */
 
57
                        dev_t res = (dev_t) bb_strtoul(devname, NULL, 16);
 
58
                        if (!errno)
 
59
                                return res;
 
60
                }
 
61
 
 
62
                devname = xasprintf("/dev/%s", devname);
 
63
        }
 
64
        /* Now devname is always "/dev/FOO" */
 
65
 
 
66
        if (stat(devname, &st) == 0 && S_ISBLK(st.st_mode))
 
67
                return st.st_rdev;
 
68
 
 
69
        /* Full blockdevs as well as partitions may be visible
 
70
         * in /sys/class/block/ even if /dev is not populated.
 
71
         */
 
72
        sysname = xasprintf("/sys/class/block/%s/dev", devname + 5);
 
73
        r = open_read_close(sysname, devfile, sizeof(devfile) - 1);
 
74
        //free(sysname);
 
75
        if (r > 0) {
 
76
                devfile[r] = '\0';
 
77
                if (sscanf(devfile, "%u:%u", &major_num, &minor_num) == 2) {
 
78
                        return makedev(major_num, minor_num);
 
79
                }
 
80
        }
 
81
 
 
82
        return (dev_t) 0;
 
83
}
 
84
 
 
85
//usage:#define resume_trivial_usage
 
86
//usage:       "BLOCKDEV [OFFSET]"
 
87
//usage:#define resume_full_usage "\n"
 
88
//usage:   "\n""Restore system state from 'suspend-to-disk' data in BLOCKDEV"
 
89
 
 
90
int resume_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 
91
int resume_main(int argc UNUSED_PARAM, char **argv)
 
92
{
 
93
        unsigned long long ofs;
 
94
        dev_t resume_device;
 
95
        char *s;
 
96
        int fd;
 
97
 
 
98
        argv++;
 
99
        if (!argv[0])
 
100
                bb_show_usage();
 
101
 
 
102
        resume_device = name_to_dev_t(argv[0]);
 
103
        if (major(resume_device) == 0) {
 
104
                bb_error_msg_and_die("invalid resume device: %s", argv[0]);
 
105
        }
 
106
        ofs = (argv[1] ? xstrtoull(argv[1], 0) : 0);
 
107
 
 
108
        fd = xopen("/sys/power/resume", O_WRONLY);
 
109
        s = xasprintf("%u:%u:%llu", major(resume_device), minor(resume_device), ofs);
 
110
 
 
111
        xwrite_str(fd, s);
 
112
        /* if write() returns, resume did not succeed */
 
113
 
 
114
        return EXIT_FAILURE; /* klibc-utils exits -1 aka 255 */
 
115
}