]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/swapon/swaplinux.c
swapon: Do not overwrite Linux swap header
[FreeBSD/FreeBSD.git] / sbin / swapon / swaplinux.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  */
4
5 #include <fcntl.h>
6 #include <err.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include "extern.h"
12
13 /*
14  * Definitions and structure taken from
15  * https://github.com/util-linux/util-linux/blob/master/include/swapheader.h
16  */
17
18 #define SWAP_VERSION 1
19 #define SWAP_UUID_LENGTH 16
20 #define SWAP_LABEL_LENGTH 16
21 #define SWAP_SIGNATURE "SWAPSPACE2"
22 #define SWAP_SIGNATURE_SZ (sizeof(SWAP_SIGNATURE) - 1)
23
24 struct swap_header_v1_2 {
25         char          bootbits[1024];    /* Space for disklabel etc. */
26         uint32_t      version;
27         uint32_t      last_page;
28         uint32_t      nr_badpages;
29         unsigned char uuid[SWAP_UUID_LENGTH];
30         char          volume_name[SWAP_LABEL_LENGTH];
31         uint32_t      padding[117];
32         uint32_t      badpages[1];
33 };
34
35 typedef union {
36         struct swap_header_v1_2 header;
37         struct {
38                 uint8_t reserved[4096 - SWAP_SIGNATURE_SZ];
39                 char    signature[SWAP_SIGNATURE_SZ];
40         } tail;
41 } swhdr_t;
42
43 #define sw_version      header.version
44 #define sw_volume_name  header.volume_name
45 #define sw_signature    tail.signature
46
47 int
48 is_linux_swap(const char *name)
49 {
50         uint8_t buf[4096];
51         swhdr_t *hdr = (swhdr_t *) buf;
52         int fd;
53
54         fd = open(name, O_RDONLY);
55         if (fd == -1)
56                 return (-1);
57
58         if (read(fd, buf, 4096) != 4096) {
59                 close(fd);
60                 return (-1);
61         }
62         close(fd);
63
64         return (hdr->sw_version == SWAP_VERSION &&
65             !memcmp(hdr->sw_signature, SWAP_SIGNATURE, SWAP_SIGNATURE_SZ));
66 }