]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
mkswap: create files with specific endianness
authorThomas Weißschuh <thomas@t-8ch.de>
Thu, 15 Dec 2022 13:32:31 +0000 (13:32 +0000)
committerThomas Weißschuh <thomas@t-8ch.de>
Thu, 15 Dec 2022 13:33:18 +0000 (13:33 +0000)
disk-utils/mkswap.8.adoc
disk-utils/mkswap.c
tests/ts/mkswap/mkswap

index 0a25a2dbed95722e8fdb7a40e5fd7cd9bb333927..904467d772592197de8bb2dd02151ef4bc664cdc 100644 (file)
@@ -70,6 +70,9 @@ generate a new randomly-generated UUID
 *time*;;
 generate a new time-based UUID
 
+*-e*, *--endianness* _ENDIANNESS_::
+Specify the _ENDIANNESS_ to use, valid arguments are *native*, *little* or *big*. The default is *native*.
+
 *-v*, *--swapversion 1*::
 Specify the swap-space version. (This option is currently pointless, as the old *-v 0* option has become obsolete and now only *-v 1* is supported. The kernel has not supported v0 swap-space format since 2.5.22 (June 2002). The new version v1 is supported since 2.1.117 (August 1998).)
 
index d14f24901c5a0848b5592b3ef4dc591b8eeb067b..6f6d3048a3b2e304634cbd4246c4880bcc51a434 100644 (file)
@@ -42,6 +42,7 @@
 #include "closestream.h"
 #include "ismounted.h"
 #include "optutils.h"
+#include "bitops.h"
 
 #ifdef HAVE_LIBUUID
 # include <uuid.h>
 
 #define SELINUX_SWAPFILE_TYPE  "swapfile_t"
 
+enum ENDIANNESS {
+       ENDIANNESS_NATIVE,
+       ENDIANNESS_LITTLE,
+       ENDIANNESS_BIG,
+};
+
 struct mkswap_control {
        struct swap_header_v1_2 *hdr;           /* swap header */
        void                    *signature_page;/* buffer with swap header */
@@ -75,12 +82,24 @@ struct mkswap_control {
 
        size_t                  nbad_extents;
 
+       enum ENDIANNESS         endianness;
+
        unsigned int            check:1,        /* --check */
                                verbose:1,      /* --verbose */
                                quiet:1,        /* --quiet */
                                force:1;        /* --force */
 };
 
+static uint32_t cpu32_to_endianness(uint32_t v, enum ENDIANNESS e)
+{
+       switch (e) {
+               case ENDIANNESS_NATIVE: return v;
+               case ENDIANNESS_LITTLE: return cpu_to_le32(v);
+               case ENDIANNESS_BIG: return cpu_to_be32(v);
+       }
+       abort();
+}
+
 static void init_signature_page(struct mkswap_control *ctl)
 {
        const int kernel_pagesize = getpagesize();
@@ -172,6 +191,9 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -L, --label LABEL         specify label\n"), out);
        fputs(_(" -v, --swapversion NUM     specify swap-space version number\n"), out);
        fputs(_(" -U, --uuid UUID           specify the uuid to use\n"), out);
+       fprintf(out,
+             _(" -e, --endianness=<value>  specify the endianness to use "
+                                           "(%s, %s or %s)\n"), "native", "little", "big");
        fputs(_("     --verbose             verbose output\n"), out);
 
        fprintf(out,
@@ -458,7 +480,7 @@ static void write_header_to_device(struct mkswap_control *ctl)
 
 int main(int argc, char **argv)
 {
-       struct mkswap_control ctl = { .fd = -1 };
+       struct mkswap_control ctl = { .fd = -1, .endianness = ENDIANNESS_NATIVE };
        int c, permMask;
        uint64_t sz;
        int version = SWAP_VERSION;
@@ -479,6 +501,7 @@ int main(int argc, char **argv)
                { "label",       required_argument, NULL, 'L' },
                { "swapversion", required_argument, NULL, 'v' },
                { "uuid",        required_argument, NULL, 'U' },
+               { "endianness",  required_argument, NULL, 'e' },
                { "version",     no_argument,       NULL, 'V' },
                { "help",        no_argument,       NULL, 'h' },
                { "lock",        optional_argument, NULL, OPT_LOCK },
@@ -497,7 +520,7 @@ int main(int argc, char **argv)
        textdomain(PACKAGE);
        close_stdout_atexit();
 
-       while((c = getopt_long(argc, argv, "cfp:qL:v:U:Vh", longopts, NULL)) != -1) {
+       while((c = getopt_long(argc, argv, "cfp:qL:v:U:e:Vh", longopts, NULL)) != -1) {
 
                err_exclusive_options(c, longopts, excl, excl_st);
 
@@ -531,6 +554,18 @@ int main(int argc, char **argv)
                                program_invocation_short_name);
 #endif
                        break;
+               case 'e':
+                       if (strcmp(optarg, "native") == 0) {
+                               ctl.endianness = ENDIANNESS_NATIVE;
+                       } else if (strcmp(optarg, "little") == 0) {
+                               ctl.endianness = ENDIANNESS_LITTLE;
+                       } else if (strcmp(optarg, "big") == 0) {
+                               ctl.endianness = ENDIANNESS_BIG;
+                       } else {
+                               errx(EXIT_FAILURE,
+                                       _("invalid endianness %s is not supported"), optarg);
+                       }
+                       break;
                case 'V':
                        print_version(EXIT_SUCCESS);
                        break;
@@ -637,9 +672,9 @@ int main(int argc, char **argv)
        wipe_device(&ctl);
 
        assert(ctl.hdr);
-       ctl.hdr->version = version;
-       ctl.hdr->last_page = ctl.npages - 1;
-       ctl.hdr->nr_badpages = ctl.nbadpages;
+       ctl.hdr->version = cpu32_to_endianness(version, ctl.endianness);
+       ctl.hdr->last_page = cpu32_to_endianness(ctl.npages - 1, ctl.endianness);
+       ctl.hdr->nr_badpages = cpu32_to_endianness(ctl.nbadpages, ctl.endianness);
 
        if ((ctl.npages - MIN_GOODPAGES) < ctl.nbadpages)
                errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable"));
index 2cb999a2779758f30608d6ec01547af8511ef2e8..fa4856b719d22c5b41872c0b7e40f9e20f7b73af 100755 (executable)
@@ -28,26 +28,38 @@ ts_check_test_command "$TS_HELPER_SYSINFO"
 ts_check_prog "xz"
 ts_check_prog "cmp"
 
-BYTE_ORDER="$("$TS_HELPER_SYSINFO" byte-order)"
 UUID=4c08e1cd-3c82-46bf-a55b-0c3270d6dfeb
 
 for PAGESIZE in 4096 8192; do
-       name="${BYTE_ORDER}-${PAGESIZE}"
-       outimg="$TS_OUTDIR/${name}.img"
-       origimg="$TS_OUTDIR/${name}.img.orig"
+       for ENDIANNESS in native little big; do
+               case "$ENDIANNESS" in 
+                       native) BYTE_ORDER="$("$TS_HELPER_SYSINFO" byte-order)";;
+                       little) BYTE_ORDER=LE;;
+                       big) BYTE_ORDER=BE;;
+               esac
 
-       ts_init_subtest $name
+               if [ "$ENDIANNESS" == "native" ]; then
+                       name="NATIVE-${PAGESIZE}"
+               else
+                       name="${BYTE_ORDER}-${PAGESIZE}"
+               fi
+               outimg="$TS_OUTDIR/${BYTE_ORDER}-${PAGESIZE}.img"
+               origimg="$TS_OUTDIR/${BYTE_ORDER}-${PAGESIZE}.img.orig"
 
-       rm -f "$outimg"
-       truncate -s $(( PAGESIZE * 10 )) "$outimg" > $TS_ERRLOG 2>&1
+               ts_init_subtest $name
 
-       "$TS_CMD_MKSWAP" -q -L label -U "$UUID" -p "$PAGESIZE" "$outimg" \
-               > "$TS_OUTPUT" 2> "$TS_ERRLOG" || ts_log "mkswap failed"
-       xz -dc "$TS_SELF/${name}.img.xz" > "$origimg"
+               rm -f "$outimg"
+               truncate -s $(( PAGESIZE * 10 )) "$outimg" > $TS_ERRLOG 2>&1
 
-       cmp "$origimg" "$outimg" > "$TS_ERRLOG" 2>&1
+               "$TS_CMD_MKSWAP" -q -L label -U "$UUID" -e "$ENDIANNESS" -p "$PAGESIZE" "$outimg" \
+                       > "$TS_OUTPUT" 2>/dev/null \
+                       || ts_log "mkswap failed"
+               xz -dc "$TS_SELF/${BYTE_ORDER}-${PAGESIZE}.img.xz" > "$origimg"
 
-       ts_finalize_subtest
+               cmp "$origimg" "$outimg" > "$TS_ERRLOG" 2>&1
+
+               ts_finalize_subtest
+       done
 done
 
 ts_finalize