blob: ad66353d35b9380103a10a386365a99b239d8e6e [file] [log] [blame]
Andrew Boied90615c2014-01-23 17:16:54 -08001#include <fcntl.h>
2#include <linux/fs.h>
Rom Lemarchand367297c2013-06-05 13:25:12 -07003#include <stdio.h>
Andrew Boied90615c2014-01-23 17:16:54 -08004#include <stdlib.h>
Rom Lemarchand367297c2013-06-05 13:25:12 -07005#include <unistd.h>
Andrew Boied90615c2014-01-23 17:16:54 -08006#include <sys/stat.h>
Rom Lemarchand367297c2013-06-05 13:25:12 -07007#include <sys/swap.h>
8#include <sys/types.h>
Rom Lemarchand367297c2013-06-05 13:25:12 -07009
Andrew Boied90615c2014-01-23 17:16:54 -080010/* This is not in a uapi header. */
Rom Lemarchand367297c2013-06-05 13:25:12 -070011struct linux_swap_header {
12 char bootbits[1024]; /* Space for disklabel etc. */
13 uint32_t version;
14 uint32_t last_page;
15 uint32_t nr_badpages;
16 unsigned char sws_uuid[16];
17 unsigned char sws_volume[16];
18 uint32_t padding[117];
19 uint32_t badpages[1];
20};
21
22#define MAGIC_SWAP_HEADER "SWAPSPACE2"
23#define MAGIC_SWAP_HEADER_LEN 10
24#define MIN_PAGES 10
25
26int mkswap_main(int argc, char **argv)
27{
Rom Lemarchand367297c2013-06-05 13:25:12 -070028 if (argc != 2) {
29 fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
Andrew Boied90615c2014-01-23 17:16:54 -080030 return EXIT_FAILURE;
Rom Lemarchand367297c2013-06-05 13:25:12 -070031 }
32
Andrew Boied90615c2014-01-23 17:16:54 -080033 int fd = open(argv[1], O_RDWR);
Rom Lemarchand367297c2013-06-05 13:25:12 -070034 if (fd < 0) {
Andrew Boied90615c2014-01-23 17:16:54 -080035 fprintf(stderr, "Cannot open %s: %s\n", argv[1], strerror(errno));
36 return EXIT_FAILURE;
Rom Lemarchand367297c2013-06-05 13:25:12 -070037 }
38
Rom Lemarchand367297c2013-06-05 13:25:12 -070039 /* Determine the length of the swap file */
Andrew Boied90615c2014-01-23 17:16:54 -080040 off64_t swap_size;
41 struct stat sb;
42 if (fstat(fd, &sb)) {
43 fprintf(stderr, "Couldn't fstat file: %s\n", strerror(errno));
44 return EXIT_FAILURE;
Rom Lemarchand367297c2013-06-05 13:25:12 -070045 }
Andrew Boied90615c2014-01-23 17:16:54 -080046 if (S_ISBLK(sb.st_mode)) {
47 if (ioctl(fd, BLKGETSIZE64, &swap_size) < 0) {
48 fprintf(stderr, "Couldn't determine block device size: %s\n", strerror(errno));
49 return EXIT_FAILURE;
50 }
51 } else {
52 swap_size = sb.st_size;
Rom Lemarchand367297c2013-06-05 13:25:12 -070053 }
54
Andrew Boied90615c2014-01-23 17:16:54 -080055 int pagesize = getpagesize();
56 if (swap_size < MIN_PAGES * pagesize) {
57 fprintf(stderr, "Swap file needs to be at least %d KiB\n", (MIN_PAGES * pagesize) >> 10);
58 return EXIT_FAILURE;
59 }
60
61 struct linux_swap_header sw_hdr;
Rom Lemarchand367297c2013-06-05 13:25:12 -070062 memset(&sw_hdr, 0, sizeof(sw_hdr));
63 sw_hdr.version = 1;
64 sw_hdr.last_page = (swap_size / pagesize) - 1;
65
Andrew Boied90615c2014-01-23 17:16:54 -080066 ssize_t len = write(fd, &sw_hdr, sizeof(sw_hdr));
Rom Lemarchand367297c2013-06-05 13:25:12 -070067 if (len != sizeof(sw_hdr)) {
Andrew Boied90615c2014-01-23 17:16:54 -080068 fprintf(stderr, "Failed to write swap header into %s: %s\n", argv[1], strerror(errno));
69 return EXIT_FAILURE;
Rom Lemarchand367297c2013-06-05 13:25:12 -070070 }
71
72 /* Write the magic header */
73 if (lseek(fd, pagesize - MAGIC_SWAP_HEADER_LEN, SEEK_SET) < 0) {
Andrew Boied90615c2014-01-23 17:16:54 -080074 fprintf(stderr, "Failed to seek into %s: %s\n", argv[1], strerror(errno));
75 return EXIT_FAILURE;
Rom Lemarchand367297c2013-06-05 13:25:12 -070076 }
77
78 len = write(fd, MAGIC_SWAP_HEADER, MAGIC_SWAP_HEADER_LEN);
79 if (len != MAGIC_SWAP_HEADER_LEN) {
Andrew Boied90615c2014-01-23 17:16:54 -080080 fprintf(stderr, "Failed to write magic swap header into %s: %s\n", argv[1], strerror(errno));
81 return EXIT_FAILURE;
Rom Lemarchand367297c2013-06-05 13:25:12 -070082 }
83
84 if (fsync(fd) < 0) {
Andrew Boied90615c2014-01-23 17:16:54 -080085 fprintf(stderr, "Failed to sync %s: %s\n", argv[1], strerror(errno));
86 return EXIT_FAILURE;
Rom Lemarchand367297c2013-06-05 13:25:12 -070087 }
Andrew Boied90615c2014-01-23 17:16:54 -080088
Rom Lemarchand367297c2013-06-05 13:25:12 -070089 close(fd);
Andrew Boied90615c2014-01-23 17:16:54 -080090 return EXIT_SUCCESS;
Rom Lemarchand367297c2013-06-05 13:25:12 -070091}