mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 09:10:28 +00:00
swapon: Do not overwrite Linux swap header
Reviewed by: imp, jhb Pull Request: https://github.com/freebsd/freebsd-src/pull/1084
This commit is contained in:
parent
4f223e0da7
commit
cf04a7775a
|
@ -6,6 +6,8 @@ LINKS= ${BINDIR}/swapon ${BINDIR}/swapoff
|
||||||
LINKS+= ${BINDIR}/swapon ${BINDIR}/swapctl
|
LINKS+= ${BINDIR}/swapon ${BINDIR}/swapctl
|
||||||
MLINKS= swapon.8 swapoff.8
|
MLINKS= swapon.8 swapoff.8
|
||||||
MLINKS+=swapon.8 swapctl.8
|
MLINKS+=swapon.8 swapctl.8
|
||||||
|
SRCS= swapon.c swaplinux.c
|
||||||
|
HDRS+= extern.h
|
||||||
|
|
||||||
LIBADD= util
|
LIBADD= util
|
||||||
|
|
||||||
|
|
5
sbin/swapon/extern.h
Normal file
5
sbin/swapon/extern.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/*-
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
int is_linux_swap(const char *);
|
66
sbin/swapon/swaplinux.c
Normal file
66
sbin/swapon/swaplinux.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*-
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "extern.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions and structure taken from
|
||||||
|
* https://github.com/util-linux/util-linux/blob/master/include/swapheader.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SWAP_VERSION 1
|
||||||
|
#define SWAP_UUID_LENGTH 16
|
||||||
|
#define SWAP_LABEL_LENGTH 16
|
||||||
|
#define SWAP_SIGNATURE "SWAPSPACE2"
|
||||||
|
#define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1)
|
||||||
|
|
||||||
|
struct swap_header_v1_2 {
|
||||||
|
char bootbits[1024]; /* Space for disklabel etc. */
|
||||||
|
uint32_t version;
|
||||||
|
uint32_t last_page;
|
||||||
|
uint32_t nr_badpages;
|
||||||
|
unsigned char uuid[SWAP_UUID_LENGTH];
|
||||||
|
char volume_name[SWAP_LABEL_LENGTH];
|
||||||
|
uint32_t padding[117];
|
||||||
|
uint32_t badpages[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct swap_header_v1_2 header;
|
||||||
|
struct {
|
||||||
|
uint8_t reserved[4096 - SWAP_SIGNATURE_SZ];
|
||||||
|
char signature[SWAP_SIGNATURE_SZ];
|
||||||
|
} tail;
|
||||||
|
} swhdr_t;
|
||||||
|
|
||||||
|
#define sw_version header.version
|
||||||
|
#define sw_volume_name header.volume_name
|
||||||
|
#define sw_signature tail.signature
|
||||||
|
|
||||||
|
int
|
||||||
|
is_linux_swap(const char *name)
|
||||||
|
{
|
||||||
|
uint8_t buf[4096];
|
||||||
|
swhdr_t *hdr = (swhdr_t *) buf;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(name, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (read(fd, buf, 4096) != 4096) {
|
||||||
|
close(fd);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return (hdr->sw_version == SWAP_VERSION &&
|
||||||
|
!memcmp(hdr->sw_signature, SWAP_SIGNATURE, SWAP_SIGNATURE_SZ));
|
||||||
|
}
|
|
@ -54,10 +54,15 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "extern.h"
|
||||||
|
|
||||||
|
#define _PATH_GNOP "/sbin/gnop"
|
||||||
|
|
||||||
static void usage(void) __dead2;
|
static void usage(void) __dead2;
|
||||||
static const char *swap_on_off(const char *, int, char *);
|
static const char *swap_on_off(const char *, int, char *);
|
||||||
static const char *swap_on_off_gbde(const char *, int);
|
static const char *swap_on_off_gbde(const char *, int);
|
||||||
static const char *swap_on_off_geli(const char *, char *, int);
|
static const char *swap_on_off_geli(const char *, char *, int);
|
||||||
|
static const char *swap_on_off_linux(const char *, int);
|
||||||
static const char *swap_on_off_md(const char *, char *, int);
|
static const char *swap_on_off_md(const char *, char *, int);
|
||||||
static const char *swap_on_off_sfile(const char *, int);
|
static const char *swap_on_off_sfile(const char *, int);
|
||||||
static void swaplist(int, int, int);
|
static void swaplist(int, int, int);
|
||||||
|
@ -250,8 +255,13 @@ swap_on_off(const char *name, int doingall, char *mntops)
|
||||||
return (swap_on_off_geli(name, mntops, doingall));
|
return (swap_on_off_geli(name, mntops, doingall));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap on special file. */
|
|
||||||
free(basebuf);
|
free(basebuf);
|
||||||
|
|
||||||
|
/* Linux swap */
|
||||||
|
if (is_linux_swap(name))
|
||||||
|
return (swap_on_off_linux(name, doingall));
|
||||||
|
|
||||||
|
/* Swap on special file. */
|
||||||
return (swap_on_off_sfile(name, doingall));
|
return (swap_on_off_sfile(name, doingall));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,6 +476,48 @@ swap_on_off_geli(const char *name, char *mntops, int doingall)
|
||||||
return (swap_on_off_sfile(name, doingall));
|
return (swap_on_off_sfile(name, doingall));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
swap_on_off_linux(const char *name, int doingall)
|
||||||
|
{
|
||||||
|
const char *ret;
|
||||||
|
char *nopname;
|
||||||
|
size_t nopnamelen;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (which_prog == SWAPON) {
|
||||||
|
/* Skip the header for Linux swap partitions */
|
||||||
|
error = run_cmd(NULL, "%s create -o 4096 %s", _PATH_GNOP,
|
||||||
|
name);
|
||||||
|
if (error) {
|
||||||
|
warnx("gnop (create) error: %s", name);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append ".nop" to name */
|
||||||
|
nopnamelen = strlen(name) + sizeof(".nop");
|
||||||
|
nopname = (char *) malloc(nopnamelen);
|
||||||
|
if (nopname == NULL)
|
||||||
|
err(1, "malloc()");
|
||||||
|
(void)strlcpy(nopname, name, nopnamelen);
|
||||||
|
(void)strlcat(nopname, ".nop", nopnamelen);
|
||||||
|
|
||||||
|
ret = swap_on_off_sfile(nopname, doingall);
|
||||||
|
|
||||||
|
if (which_prog == SWAPOFF) {
|
||||||
|
error = run_cmd(NULL, "%s destroy %s", _PATH_GNOP, nopname);
|
||||||
|
if (error) {
|
||||||
|
warnx("gnop (destroy) error: %s", name);
|
||||||
|
free(nopname);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(nopname);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
swap_on_off_md(const char *name, char *mntops, int doingall)
|
swap_on_off_md(const char *name, char *mntops, int doingall)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue