5 |
* |
* |
6 |
* Licensed under GPL version 2, see file LICENSE in this tarball for details. |
* Licensed under GPL version 2, see file LICENSE in this tarball for details. |
7 |
*/ |
*/ |
|
|
|
8 |
#include "libbb.h" |
#include "libbb.h" |
9 |
|
|
10 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
47 |
bb_perror_msg_and_die("SELinux relabeling failed"); |
bb_perror_msg_and_die("SELinux relabeling failed"); |
48 |
} |
} |
49 |
#else |
#else |
50 |
#define mkswap_selinux_setcontext(fd, path) ((void)0) |
# define mkswap_selinux_setcontext(fd, path) ((void)0) |
51 |
#endif |
#endif |
52 |
|
|
53 |
#if 0 /* from Linux 2.6.23 */ |
/* from Linux 2.6.23 */ |
54 |
/* |
/* |
55 |
* Magic header for a swap area. The first part of the union is |
* Magic header for a swap area. ... Note that the first |
56 |
* what the swap magic looks like for the old (limited to 128MB) |
* kilobyte is reserved for boot loader or disk label stuff. |
|
* swap area format, the second part of the union adds - in the |
|
|
* old reserved area - some extra information. Note that the first |
|
|
* kilobyte is reserved for boot loader or disk label stuff... |
|
57 |
*/ |
*/ |
58 |
union swap_header { |
struct swap_header_v1 { |
59 |
struct { |
/* char bootbits[1024]; Space for disklabel etc. */ |
60 |
char reserved[PAGE_SIZE - 10]; |
uint32_t version; /* second kbyte, word 0 */ |
61 |
char magic[10]; /* SWAP-SPACE or SWAPSPACE2 */ |
uint32_t last_page; /* 1 */ |
62 |
} magic; |
uint32_t nr_badpages; /* 2 */ |
63 |
struct { |
char sws_uuid[16]; /* 3,4,5,6 */ |
64 |
char bootbits[1024]; /* Space for disklabel etc. */ |
char sws_volume[16]; /* 7,8,9,10 */ |
65 |
__u32 version; /* second kbyte, word 0 */ |
uint32_t padding[117]; /* 11..127 */ |
66 |
__u32 last_page; /* 1 */ |
uint32_t badpages[1]; /* 128 */ |
67 |
__u32 nr_badpages; /* 2 */ |
/* total 129 32-bit words in 2nd kilobyte */ |
|
unsigned char sws_uuid[16]; /* 3,4,5,6 */ |
|
|
unsigned char sws_volume[16]; /* 7,8,9,10 */ |
|
|
__u32 padding[117]; /* 11..127 */ |
|
|
__u32 badpages[1]; /* 128, total 129 32-bit words */ |
|
|
} info; |
|
68 |
}; |
}; |
|
#endif |
|
69 |
|
|
70 |
#define NWORDS 129 |
#define NWORDS 129 |
71 |
#define hdr ((uint32_t*)(&bb_common_bufsiz1)) |
#define hdr ((struct swap_header_v1*)bb_common_bufsiz1) |
72 |
|
|
73 |
struct BUG_bufsiz1_is_too_small { |
struct BUG_sizes { |
74 |
char BUG_bufsiz1_is_too_small[COMMON_BUFSIZE < (NWORDS * 4) ? -1 : 1]; |
char swap_header_v1_wrong[sizeof(*hdr) != (NWORDS * 4) ? -1 : 1]; |
75 |
|
char bufsiz1_is_too_small[COMMON_BUFSIZE < (NWORDS * 4) ? -1 : 1]; |
76 |
}; |
}; |
77 |
|
|
78 |
/* Stored without terminating NUL */ |
/* Stored without terminating NUL */ |
79 |
static const char SWAPSPACE2[sizeof("SWAPSPACE2")-1] ALIGN1 = "SWAPSPACE2"; |
static const char SWAPSPACE2[sizeof("SWAPSPACE2")-1] ALIGN1 = "SWAPSPACE2"; |
80 |
|
|
81 |
int mkswap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int mkswap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
82 |
int mkswap_main(int argc, char **argv) |
int mkswap_main(int argc UNUSED_PARAM, char **argv) |
83 |
{ |
{ |
84 |
int fd, pagesize; |
int fd; |
85 |
|
unsigned pagesize; |
86 |
off_t len; |
off_t len; |
87 |
|
const char *label = ""; |
88 |
|
|
89 |
// No options supported. |
opt_complementary = "=1"; |
90 |
|
/* TODO: -p PAGESZ, -U UUID, |
91 |
|
* optional SIZE_IN_KB 2nd param |
92 |
|
*/ |
93 |
|
getopt32(argv, "L:", &label); |
94 |
|
argv += optind; |
95 |
|
|
96 |
if (argc != 2) bb_show_usage(); |
fd = xopen(argv[0], O_WRONLY); |
97 |
|
|
98 |
// Figure out how big the device is and announce our intentions. |
/* Figure out how big the device is and announce our intentions */ |
|
|
|
|
fd = xopen(argv[1], O_RDWR); |
|
99 |
/* fdlength was reported to be unreliable - use seek */ |
/* fdlength was reported to be unreliable - use seek */ |
100 |
len = xlseek(fd, 0, SEEK_END); |
len = xlseek(fd, 0, SEEK_END); |
101 |
#if ENABLE_SELINUX |
if (ENABLE_SELINUX) |
102 |
xlseek(fd, 0, SEEK_SET); |
xlseek(fd, 0, SEEK_SET); |
|
#endif |
|
|
pagesize = getpagesize(); |
|
|
printf("Setting up swapspace version 1, size = %"OFF_FMT"u bytes\n", |
|
|
len - pagesize); |
|
|
mkswap_selinux_setcontext(fd, argv[1]); |
|
|
|
|
|
// Make a header. hdr is zero-filled so far... |
|
|
hdr[0] = 1; |
|
|
hdr[1] = (len / pagesize) - 1; |
|
103 |
|
|
104 |
// Write the header. Sync to disk because some kernel versions check |
pagesize = getpagesize(); |
105 |
// signature on disk (not in cache) during swapon. |
len -= pagesize; |
106 |
|
printf("Setting up swapspace version 1, size = %"OFF_FMT"u bytes\n", len); |
107 |
|
mkswap_selinux_setcontext(fd, argv[0]); |
108 |
|
|
109 |
|
/* Make a header. hdr is zero-filled so far... */ |
110 |
|
hdr->version = 1; |
111 |
|
hdr->last_page = (uoff_t)len / pagesize; |
112 |
|
|
113 |
|
if (ENABLE_FEATURE_MKSWAP_UUID) { |
114 |
|
char uuid_string[32]; |
115 |
|
generate_uuid((void*)hdr->sws_uuid); |
116 |
|
bin2hex(uuid_string, hdr->sws_uuid, 16); |
117 |
|
/* f.e. UUID=dfd9c173-be52-4d27-99a5-c34c6c2ff55f */ |
118 |
|
printf("UUID=%.8s" "-%.4s-%.4s-%.4s-%.12s\n", |
119 |
|
uuid_string, |
120 |
|
uuid_string+8, |
121 |
|
uuid_string+8+4, |
122 |
|
uuid_string+8+4+4, |
123 |
|
uuid_string+8+4+4+4 |
124 |
|
); |
125 |
|
} |
126 |
|
safe_strncpy(hdr->sws_volume, label, 16); |
127 |
|
|
128 |
|
/* Write the header. Sync to disk because some kernel versions check |
129 |
|
* signature on disk (not in cache) during swapon. */ |
130 |
xlseek(fd, 1024, SEEK_SET); |
xlseek(fd, 1024, SEEK_SET); |
131 |
xwrite(fd, hdr, NWORDS * 4); |
xwrite(fd, hdr, NWORDS * 4); |
132 |
xlseek(fd, pagesize - 10, SEEK_SET); |
xlseek(fd, pagesize - 10, SEEK_SET); |
133 |
xwrite(fd, SWAPSPACE2, 10); |
xwrite(fd, SWAPSPACE2, 10); |
134 |
fsync(fd); |
fsync(fd); |
135 |
|
|
136 |
if (ENABLE_FEATURE_CLEAN_UP) close(fd); |
if (ENABLE_FEATURE_CLEAN_UP) |
137 |
|
close(fd); |
138 |
|
|
139 |
return 0; |
return 0; |
140 |
} |
} |