From: Thomas Weißschuh Date: Fri, 28 Apr 2023 18:42:01 +0000 (+0200) Subject: mkswap: implement --offset X-Git-Tag: v2.40-rc1~467^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=84ec6f99f7927e5dc05a20f133b21f5870923ff1;p=thirdparty%2Futil-linux.git mkswap: implement --offset Addresses #2166 Signed-off-by: Thomas Weißschuh --- diff --git a/bash-completion/mkswap b/bash-completion/mkswap index 61157ef13e..33b0a70ceb 100644 --- a/bash-completion/mkswap +++ b/bash-completion/mkswap @@ -21,13 +21,17 @@ _mkswap_module() COMPREPLY=( $(compgen -W "$(uuidgen -r)" -- $cur) ) return 0 ;; + '-o'|'--offset') + COMPREPLY=( $(compgen -W "bytes" -- $cur) ) + return 0 + ;; '-h'|'--help'|'-V'|'--version') return 0 ;; esac case $cur in -*) - OPTS="--check --force --pagesize --lock --label --swapversion --uuid --verbose --version --help" + OPTS="--check --force --pagesize --lock --label --swapversion --uuid --offset --verbose --version --help" COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) ) return 0 ;; diff --git a/disk-utils/mkswap.8.adoc b/disk-utils/mkswap.8.adoc index 904467d772..ad48c99e08 100644 --- a/disk-utils/mkswap.8.adoc +++ b/disk-utils/mkswap.8.adoc @@ -73,6 +73,9 @@ 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*. +*-o*, *--offset* _offset_:: +Specify the _offset_ to write the swap area to. + *-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).) diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index bd02301774..b6deadf38a 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -76,6 +76,7 @@ struct mkswap_control { int user_pagesize; /* --pagesize */ int pagesize; /* final pagesize used for the header */ + off_t offset; /* offset of the header in the target */ char *opt_label; /* LABEL as specified on command line */ unsigned char *uuid; /* UUID parsed by libbuuid */ @@ -194,6 +195,7 @@ static void __attribute__((__noreturn__)) usage(void) fprintf(out, _(" -e, --endianness= specify the endianness to use " "(%s, %s or %s)\n"), "native", "little", "big"); + fputs(_(" -o, --offset OFFSET specify the offset in the device\n"), out); fputs(_(" --verbose verbose output\n"), out); fprintf(out, @@ -347,6 +349,9 @@ static unsigned long long get_size(const struct mkswap_control *ctl) err(EXIT_FAILURE, _("cannot open %s"), ctl->devname); if (blkdev_get_size(fd, &size) < 0) err(EXIT_FAILURE, _("cannot determine size of %s"), ctl->devname); + if ((unsigned long long) ctl->offset > size) + errx(EXIT_FAILURE, _("offset larger than file size")); + size -= ctl->offset; size /= ctl->pagesize; close(fd); @@ -465,11 +470,15 @@ static void wipe_device(struct mkswap_control *ctl) static void write_header_to_device(struct mkswap_control *ctl) { + off_t offset; + assert(ctl); assert(ctl->fd > -1); assert(ctl->signature_page); - if (lseek(ctl->fd, SIGNATURE_OFFSET, SEEK_SET) != SIGNATURE_OFFSET) + offset = SIGNATURE_OFFSET + ctl->offset; + + if (lseek(ctl->fd, offset, SEEK_SET) != offset) errx(EXIT_FAILURE, _("unable to rewind swap-device")); if (write_all(ctl->fd, (char *) ctl->signature_page + SIGNATURE_OFFSET, @@ -503,6 +512,7 @@ int main(int argc, char **argv) { "swapversion", required_argument, NULL, 'v' }, { "uuid", required_argument, NULL, 'U' }, { "endianness", required_argument, NULL, 'e' }, + { "offset", required_argument, NULL, 'o' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, { "lock", optional_argument, NULL, OPT_LOCK }, @@ -521,7 +531,7 @@ int main(int argc, char **argv) textdomain(PACKAGE); close_stdout_atexit(); - while((c = getopt_long(argc, argv, "cfp:qL:v:U:e:Vh", longopts, NULL)) != -1) { + while((c = getopt_long(argc, argv, "cfp:qL:v:U:e:o:Vh", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); @@ -567,6 +577,10 @@ int main(int argc, char **argv) _("invalid endianness %s is not supported"), optarg); } break; + case 'o': + ctl.offset = str2unum_or_err(optarg, + 10, _("Invalid offset"), SINT_MAX(off_t)); + break; case 'V': print_version(EXIT_SUCCESS); break; diff --git a/tests/ts/mkswap/mkswap b/tests/ts/mkswap/mkswap index bed7941899..c4fdce4f03 100755 --- a/tests/ts/mkswap/mkswap +++ b/tests/ts/mkswap/mkswap @@ -63,4 +63,28 @@ for PAGESIZE in 4096 8192; do done done +ts_init_subtest offset + +offset=10000 +outimg="$TS_OUTDIR/offset.img" + +rm -f "$outimg" +truncate -s $(( 4096 * 10 )) "$outimg" > $TS_ERRLOG 2>&1 + +rm -f "$outimg.offset" +truncate -s $(( 4096 * 10 + $offset )) "$outimg.offset" > $TS_ERRLOG 2>&1 + +"$TS_CMD_MKSWAP" -q -U "$UUID" -p 4096 "$outimg" \ + >> "$TS_OUTPUT" 2>/dev/null \ + || ts_log "mkswap failed" + +"$TS_CMD_MKSWAP" -q -U "$UUID" -p 4096 -o "$offset" "$outimg.offset" \ + >> "$TS_OUTPUT" 2>/dev/null \ + || ts_log "mkswap -o failed" + +cmp -n "$offset" "$outimg.offset" /dev/zero >> "$TS_ERRLOG" 2>&1 +cmp "$outimg" "$outimg.offset" 0 "$offset" >> "$TS_ERRLOG" 2>&1 + +ts_finalize_subtest + ts_finalize