X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=util-linux%2Fmkswap.c;h=7e32d91edba94396543a4b03471e83dfbaca0edc;hb=4f0408b5bc6ed726e7f98d6adedede41337b9b74;hp=7baa3ecfb4ecef55b9ddd87eaa2f7d6ceffa5a5b;hpb=d398ecab9d6e42b1091d214df50bf938030d11a2;p=oweals%2Fbusybox.git diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 7baa3ecfb..7e32d91ed 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c @@ -5,43 +5,132 @@ * * Licensed under GPL version 2, see file LICENSE in this tarball for details. */ +#include "libbb.h" -#include "busybox.h" +#if ENABLE_SELINUX +static void mkswap_selinux_setcontext(int fd, const char *path) +{ + struct stat stbuf; + + if (!is_selinux_enabled()) + return; + + if (fstat(fd, &stbuf) < 0) + bb_perror_msg_and_die("fstat failed"); + if (S_ISREG(stbuf.st_mode)) { + security_context_t newcon; + security_context_t oldcon = NULL; + context_t context; -int mkswap_main(int argc, char *argv[]) + if (fgetfilecon(fd, &oldcon) < 0) { + if (errno != ENODATA) + goto error; + if (matchpathcon(path, stbuf.st_mode, &oldcon) < 0) + goto error; + } + context = context_new(oldcon); + if (!context || context_type_set(context, "swapfile_t")) + goto error; + newcon = context_str(context); + if (!newcon) + goto error; + /* fsetfilecon_raw is hidden */ + if (strcmp(oldcon, newcon) != 0 && fsetfilecon(fd, newcon) < 0) + goto error; + if (ENABLE_FEATURE_CLEAN_UP) { + context_free(context); + freecon(oldcon); + } + } + return; + error: + bb_perror_msg_and_die("SELinux relabeling failed"); +} +#else +# define mkswap_selinux_setcontext(fd, path) ((void)0) +#endif + +/* 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 */ + char 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; + +#define NWORDS 129 +#define hdr ((struct swap_header_v1*)bb_common_bufsiz1) + +struct BUG_sizes { + char swap_header_v1_wrong[sizeof(*hdr) != (NWORDS * 4) ? -1 : 1]; + 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) { - int fd, pagesize; + int fd; + unsigned pagesize; off_t len; - unsigned int hdr[129]; - - // No options supported. + const char *label = ""; - if (argc != 2) bb_show_usage(); + opt_complementary = "-1"; /* at least one param */ + /* TODO: -p PAGESZ, -U UUID */ + getopt32(argv, "L:", &label); + argv += optind; - // Figure out how big the device is and announce our intentions. + fd = xopen(argv[0], O_WRONLY); - fd = xopen(argv[1], O_RDWR); - len = fdlength(fd); + /* Figure out how big the device is */ + len = get_volume_size_in_bytes(fd, argv[1], 1024, /*extend:*/ 1); pagesize = getpagesize(); - printf("Setting up swapspace version 1, size = %"OFF_FMT"d bytes\n", - len - pagesize); + len -= pagesize; - // Make a header. + /* Announce our intentions */ + printf("Setting up swapspace version 1, size = %"OFF_FMT"u bytes\n", len); + mkswap_selinux_setcontext(fd, argv[0]); - memset(hdr, 0, sizeof(hdr)); - hdr[0] = 1; - hdr[1] = (len / pagesize) - 1; + /* Make a header. hdr is zero-filled so far... */ + hdr->version = 1; + hdr->last_page = (uoff_t)len / pagesize; - // Write the header. Sync to disk because some kernel versions check - // signature on disk (not in cache) during swapon. + if (ENABLE_FEATURE_MKSWAP_UUID) { + char uuid_string[32]; + generate_uuid((void*)hdr->sws_uuid); + bin2hex(uuid_string, hdr->sws_uuid, 16); + /* f.e. UUID=dfd9c173-be52-4d27-99a5-c34c6c2ff55f */ + printf("UUID=%.8s" "-%.4s-%.4s-%.4s-%.12s\n", + uuid_string, + uuid_string+8, + uuid_string+8+4, + uuid_string+8+4+4, + uuid_string+8+4+4+4 + ); + } + safe_strncpy(hdr->sws_volume, label, 16); + /* Write the header. Sync to disk because some kernel versions check + * signature on disk (not in cache) during swapon. */ xlseek(fd, 1024, SEEK_SET); - xwrite(fd, hdr, sizeof(hdr)); - xlseek(fd, pagesize-10, SEEK_SET); - xwrite(fd, "SWAPSPACE2", 10); + xwrite(fd, hdr, NWORDS * 4); + xlseek(fd, pagesize - 10, SEEK_SET); + xwrite(fd, SWAPSPACE2, 10); fsync(fd); - if (ENABLE_FEATURE_CLEAN_UP) close(fd); + if (ENABLE_FEATURE_CLEAN_UP) + close(fd); return 0; }