3 Copyright (C) 2009 Rob Landley <rob@landley.net>
4 Copyright (C) 2012 rofl0r
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted.
9 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #include <ulz/stdio-repl.h>
28 #if !defined(_Noreturn) && __STDC_VERSION__+0 < 201112L
30 #define _Noreturn __attribute__((noreturn))
36 _Noreturn
static void usage(void) {
37 printf("usage: mkswap path-to-blockdevice\n");
41 _Noreturn
static void die(const char* msg
) {
46 #include <sys/ioctl.h>
47 #include <sys/mount.h>
49 // Return how long the file at fd is, if there's any way to determine it.
50 static off_t
fdlength(int fd
) {
51 off_t bottom
= 0, top
= 0, pos
, old
;
54 // If the ioctl works for this, return it.
56 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) return size
*512L;
58 // If not, do a binary search for the last location we can read. (Some
59 // block devices don't do BLKGETSIZE right.) This should probably have
62 old
= lseek(fd
, 0, SEEK_CUR
);
66 pos
= bottom
+ (top
- bottom
) / 2;
68 // If we can read from the current location, it's bigger.
70 if (lseek(fd
, pos
, 0)>=0 && read(fd
, &temp
, 1)==1) {
71 if (bottom
== top
) bottom
= top
= (top
+1) * 2;
74 // If we can't, it's smaller.
82 } while (bottom
+ 1 != top
);
84 lseek(fd
, old
, SEEK_SET
);
89 int main(int argc
, char** argv
) {
91 if(argc
!= 2) usage();
92 if ((fd
= open(argv
[1], O_RDWR
)) == -1) die("open");
94 size_t pagesize
= sysconf(_SC_PAGE_SIZE
);
95 off_t len
= fdlength(fd
);
96 if (len
< (ssize_t
) pagesize
)
99 size_t pages
= (len
/pagesize
)-1;
100 unsigned int swap
[129] = {0};
102 // Write header. Note that older kernel versions checked signature
103 // on disk (not in cache) during swapon, so sync after writing.
107 lseek(fd
, 1024, SEEK_SET
);
108 write(fd
, swap
, 129*sizeof(unsigned int));
109 lseek(fd
, pagesize
-10, SEEK_SET
);
110 write(fd
, "SWAPSPACE2", 10);
115 printf("Swapspace size: %luk\n", pages
*(unsigned long)(pagesize
/1024));