hush: get rid of charmap[]
[oweals/busybox.git] / util-linux / mkswap.c
1 /* vi: set sw=4 ts=4: */
2 /* mkswap.c - format swap device (Linux v1 only)
3  *
4  * Copyright 2006 Rob Landley <rob@landley.net>
5  *
6  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
7  */
8
9 #include "libbb.h"
10
11 #if ENABLE_SELINUX
12 static void mkswap_selinux_setcontext(int fd, const char *path)
13 {
14         struct stat stbuf;
15
16         if (!is_selinux_enabled())
17                 return;
18
19         if (fstat(fd, &stbuf) < 0)
20                 bb_perror_msg_and_die("fstat failed");
21         if (S_ISREG(stbuf.st_mode)) {
22                 security_context_t newcon;
23                 security_context_t oldcon = NULL;
24                 context_t context;
25
26                 if (fgetfilecon(fd, &oldcon) < 0) {
27                         if (errno != ENODATA)
28                                 goto error;
29                         if (matchpathcon(path, stbuf.st_mode, &oldcon) < 0)
30                                 goto error;
31                 }
32                 context = context_new(oldcon);
33                 if (!context || context_type_set(context, "swapfile_t"))
34                         goto error;
35                 newcon = context_str(context);
36                 if (!newcon)
37                         goto error;
38                 /* fsetfilecon_raw is hidden */
39                 if (strcmp(oldcon, newcon) != 0 && fsetfilecon(fd, newcon) < 0)
40                         goto error;
41                 if (ENABLE_FEATURE_CLEAN_UP) {
42                         context_free(context);
43                         freecon(oldcon);
44                 }
45         }
46         return;
47  error:
48         bb_perror_msg_and_die("SELinux relabeling failed");
49 }
50 #else
51 #define mkswap_selinux_setcontext(fd, path) ((void)0)
52 #endif
53
54 #if 0 /* from Linux 2.6.23 */
55 /*
56  * Magic header for a swap area. The first part of the union is
57  * what the swap magic looks like for the old (limited to 128MB)
58  * swap area format, the second part of the union adds - in the
59  * old reserved area - some extra information. Note that the first
60  * kilobyte is reserved for boot loader or disk label stuff...
61  */
62 union swap_header {
63         struct {
64                 char reserved[PAGE_SIZE - 10];
65                 char magic[10];                 /* SWAP-SPACE or SWAPSPACE2 */
66         } magic;
67         struct {
68                 char            bootbits[1024]; /* Space for disklabel etc. */
69                 __u32           version;        /* second kbyte, word 0 */
70                 __u32           last_page;      /* 1 */
71                 __u32           nr_badpages;    /* 2 */
72                 unsigned char   sws_uuid[16];   /* 3,4,5,6 */
73                 unsigned char   sws_volume[16]; /* 7,8,9,10  */
74                 __u32           padding[117];   /* 11..127 */
75                 __u32           badpages[1];    /* 128, total 129 32-bit words */
76         } info;
77 };
78 #endif
79
80 #define NWORDS 129
81 #define hdr ((uint32_t*)(&bb_common_bufsiz1))
82
83 struct BUG_bufsiz1_is_too_small {
84         char BUG_bufsiz1_is_too_small[COMMON_BUFSIZE < (NWORDS * 4) ? -1 : 1];
85 };
86
87 /* Stored without terminating NUL */
88 static const char SWAPSPACE2[sizeof("SWAPSPACE2")-1] ALIGN1 = "SWAPSPACE2";
89
90 int mkswap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
91 int mkswap_main(int argc, char **argv)
92 {
93         int fd, pagesize;
94         off_t len;
95
96         // No options supported.
97
98         if (argc != 2) bb_show_usage();
99
100         // Figure out how big the device is and announce our intentions.
101
102         fd = xopen(argv[1], O_RDWR);
103         /* fdlength was reported to be unreliable - use seek */
104         len = xlseek(fd, 0, SEEK_END);
105 #if ENABLE_SELINUX
106         xlseek(fd, 0, SEEK_SET);
107 #endif
108         pagesize = getpagesize();
109         printf("Setting up swapspace version 1, size = %"OFF_FMT"u bytes\n",
110                         len - pagesize);
111         mkswap_selinux_setcontext(fd, argv[1]);
112
113         // Make a header. hdr is zero-filled so far...
114         hdr[0] = 1;
115         hdr[1] = (len / pagesize) - 1;
116
117         // Write the header.  Sync to disk because some kernel versions check
118         // signature on disk (not in cache) during swapon.
119
120         xlseek(fd, 1024, SEEK_SET);
121         xwrite(fd, hdr, NWORDS * 4);
122         xlseek(fd, pagesize - 10, SEEK_SET);
123         xwrite(fd, SWAPSPACE2, 10);
124         fsync(fd);
125
126         if (ENABLE_FEATURE_CLEAN_UP) close(fd);
127
128         return 0;
129 }