swaplabel: new applet
No binary (build failed)
—
(log yok)
| @@ -2485,6 +2485,10 @@ extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */ | |
| */ | |
| #define bb_default_path (bb_PATH_root_path + sizeof("PATH=/sbin:/usr/sbin")) | |
| + | /* Stored without terminating NUL */ |
| + | extern const char bb_SWAPSPACE2[sizeof("SWAPSPACE2")-1]; |
| + | |
| + | |
| extern const int const_int_0; | |
| //extern const int const_int_1; | |
| @@ -14,35 +14,44 @@ uoff_t FAST_FUNC get_volume_size_in_bytes(int fd, | |
| int extend) | |
| { | |
| uoff_t result; | |
| + | #define ULL(x) ((unsigned long long)(x)) |
| if (override) { | |
| result = XATOOFF(override); | |
| if (result >= (uoff_t)(MAXINT(off_t)) / override_units) | |
| - | bb_simple_error_msg_and_die("image size is too big"); |
| + | bb_error_msg_and_die("image size %lld is too big", ULL(result)); |
| result *= override_units; | |
| - | /* seek past end fails on block devices but works on files */ |
| + | if (result == 0) |
| + | goto insane; |
| + | // Do we need to extend the file? |
| + | // Seek past end fails on block devices but works on files! |
| if (lseek(fd, result - 1, SEEK_SET) != (off_t)-1) { | |
| - | if (extend) |
| - | xwrite(fd, "", 1); /* file grows if needed */ |
| + | char dummy; |
| + | if (extend && safe_read(fd, &dummy, 1) != 1) { |
| + | // the file is shorter |
| + | xwrite(fd, "", 1); // grow it |
| + | } |
| } | |
| //else { | |
| // bb_error_msg("warning, block device is smaller"); | |
| //} | |
| } else { | |
| - | /* more portable than BLKGETSIZE[64] */ |
| + | // more portable than BLKGETSIZE[64] |
| result = xlseek(fd, 0, SEEK_END); | |
| } | |
| xlseek(fd, 0, SEEK_SET); | |
| - | /* Prevent things like this: |
| - | * $ dd if=/dev/zero of=foo count=1 bs=1024 |
| - | * $ mkswap foo |
| - | * Setting up swapspace version 1, size = 18446744073709548544 bytes |
| - | * |
| - | * Picked 16k arbitrarily: */ |
| - | if (result < 16*1024) |
| - | bb_simple_error_msg_and_die("image is too small"); |
| + | // Prevent things like this: |
| + | // $ dd if=/dev/zero of=foo count=1 bs=1024 |
| + | // $ mkswap foo |
| + | // Setting up swapspace version 1, size = 18446744073709548544 bytes |
| + | // |
| + | // Picked 16k arbitrarily: |
| + | if (result < 16*1024) { |
| + | insane: |
| + | bb_error_msg_and_die("image is too small: %lld bytes", ULL(result)); |
| + | } |
| return result; | |
| } | |
| @@ -33,6 +33,11 @@ const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; | |
| * but I want to save a few bytes here. Check libbb.h before changing! */ | |
| const char bb_PATH_root_path[] ALIGN1 = BB_PATH_ROOT_PATH; | |
| + | #if ENABLE_MKSWAP || ENABLE_SWAPLABEL |
| + | /* Stored without terminating NUL */ |
| + | const char bb_SWAPSPACE2[sizeof("SWAPSPACE2")-1] ALIGN1 = "SWAPSPACE2"; |
| + | #endif |
| + | |
| //const int const_int_1 = 1; | |
| /* explicitly = 0, otherwise gcc may make it a common variable | |
| @@ -107,9 +107,6 @@ struct BUG_sizes { | |
| char bufsiz1_is_too_small[COMMON_BUFSIZE < (NWORDS * 4) ? -1 : 1]; | |
| }; | |
| - | /* Stored without terminating NUL */ |
| - | static const char SWAPSPACE2[sizeof("SWAPSPACE2")-1] ALIGN1 = "SWAPSPACE2"; |
| - | |
| int mkswap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int mkswap_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| @@ -160,7 +157,7 @@ int mkswap_main(int argc UNUSED_PARAM, char **argv) | |
| * signature on disk (not in cache) during swapon. */ | |
| xwrite(fd, hdr, NWORDS * 4); | |
| xlseek(fd, pagesize - 10, SEEK_SET); | |
| - | xwrite(fd, SWAPSPACE2, 10); |
| + | xwrite(fd, bb_SWAPSPACE2, 10); |
| fsync(fd); | |
| if (ENABLE_FEATURE_CLEAN_UP) | |
| @@ -0,0 +1,83 @@ | |
| + | /* vi: set sw=4 ts=4: */ |
| + | /* |
| + | * Copyright 2026 Denys Vlasenko <[email protected]> |
| + | * |
| + | * Licensed under GPLv2, see file LICENSE in this source tree. |
| + | */ |
| + | //config:config SWAPLABEL |
| + | //config: bool "swaplabel (1 kb)" |
| + | //config: default y |
| + | //config: help |
| + | //config: swaplabel shows or sets swap's label. |
| + | |
| + | //applet:IF_SWAPLABEL(APPLET(swaplabel, BB_DIR_SBIN, BB_SUID_DROP)) |
| + | |
| + | //kbuild:lib-$(CONFIG_SWAPLABEL) += swaplabel.o |
| + | |
| + | //usage:#define swaplabel_trivial_usage |
| + | //usage: "[-L LBL] BLOCKDEV" |
| + | //usage:#define swaplabel_full_usage "\n\n" |
| + | //usage: "Show or set swap label on BLOCKDEV\n" |
| + | //usage: "\n -L LBL Label" |
| + | |
| + | #include "libbb.h" |
| + | #include "common_bufsiz.h" |
| + | |
| + | /* from Linux 2.6.23 */ |
| + | /* |
| + | * Magic header for a swap area. ... Note that the first |
| + | * kilobyte is reserved for boot loader or disk label stuff. |
| + | */ |
| + | struct swap_header_v1 { |
| + | /* char bootbits[1024]; Space for disklabel etc. */ |
| + | uint32_t version; /* second kbyte, word 0 */ |
| + | uint32_t last_page; /* 1 */ |
| + | uint32_t nr_badpages; /* 2 */ |
| + | uint8_t sws_uuid[16]; /* 3,4,5,6 */ |
| + | char sws_volume[16]; /* 7,8,9,10 */ |
| + | uint32_t padding[117]; /* 11..127 */ |
| + | uint32_t badpages[1]; /* 128 */ |
| + | /* total 129 32-bit words in 2nd kilobyte */ |
| + | } FIX_ALIASING; |
| + | |
| + | int swaplabel_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| + | int swaplabel_main(int argc UNUSED_PARAM, char **argv) |
| + | { |
| + | char buf32[32]; |
| + | const char *label = NULL; |
| + | int fd; |
| + | |
| + | // TODO: -U UUID |
| + | getopt32(argv, "^" "L:" "\0" "=1"/*exactly one arg*/, &label); |
| + | argv += optind; |
| + | |
| + | fd = xopen(argv[0], label ? O_RDWR : O_RDONLY); |
| + | |
| + | xlseek(fd, bb_getpagesize() - 10, SEEK_SET); |
| + | xread(fd, buf32, 10); |
| + | if (memcmp(buf32, bb_SWAPSPACE2, 10) != 0) |
| + | bb_error_msg_and_die("%s: not a valid swap partition", argv[0]); |
| + | // TODO: also check hdr.version == 1? |
| + | |
| + | xlseek(fd, 1024 + offsetof(struct swap_header_v1, sws_uuid) + 16 * (!!label), SEEK_SET); |
| + | if (label) { |
| + | int sz = strnlen(label, 15) + 1; // includes NUL unless full 16 bytes |
| + | xwrite(fd, label, sz); |
| + | // BTW, writing to active swap partition fails with ETXTBUSY! |
| + | } else { |
| + | char uuid_string37[37]; |
| + | |
| + | xread(fd, buf32, 32); |
| + | if (buf32[16]) |
| + | printf("LABEL: %.16s\n", buf32 + 16); |
| + | |
| + | // f.e. dfd9c173-be52-4d27-99a5-c34c6c2ff55f |
| + | format_uuid_DCE_37_chars(uuid_string37, (uint8_t*)buf32); |
| + | printf("UUID: %s\n", uuid_string37); |
| + | } |
| + | |
| + | if (ENABLE_FEATURE_CLEAN_UP) |
| + | close(fd); |
| + | |
| + | return 0; |
| + | } |
| @@ -58,7 +58,7 @@ int FAST_FUNC volume_id_probe_linux_swap(struct volume_id *id /*,uint64_t off*/) | |
| goto found; | |
| } | |
| - | if (memcmp(buf, "SWAPSPACE2", 10) == 0 |
| + | if (memcmp(buf, bb_SWAPSPACE2, 10) == 0 |
| || memcmp(buf, "S1SUSPEND", 9) == 0 | |
| || memcmp(buf, "S2SUSPEND", 9) == 0 | |
| || memcmp(buf, "ULSUSPEND", 9) == 0 | |