add netbsd nl(1)
[rofl0r-hardcore-utils.git] / mkswap.c
blobeeca1a82693f94e2072b71c86ee0ffbe5d6f4bac
1 /*
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.
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <sys/stat.h>
24 #ifdef USE_LIBULZ
25 #include <ulz/stdio-repl.h>
26 #endif
28 #if !defined(_Noreturn) && __STDC_VERSION__+0 < 201112L
29 #ifdef __GNUC__
30 #define _Noreturn __attribute__((noreturn))
31 #else
32 #define _Noreturn
33 #endif
34 #endif
36 _Noreturn static void usage(void) {
37 printf("usage: mkswap path-to-blockdevice\n");
38 exit(1);
41 _Noreturn static void die(const char* msg) {
42 perror(msg);
43 exit(1);
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;
52 int size;
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
60 // a CONFIG option...
62 old = lseek(fd, 0, SEEK_CUR);
63 do {
64 char temp;
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;
72 else bottom = pos;
74 // If we can't, it's smaller.
76 } else {
77 if (bottom == top) {
78 if (!top) return 0;
79 bottom = top/2;
80 } else top = pos;
82 } while (bottom + 1 != top);
84 lseek(fd, old, SEEK_SET);
86 return pos + 1;
89 int main(int argc, char** argv) {
90 int fd;
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)
97 die("file to small");
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.
105 swap[0] = 1;
106 swap[1] = pages;
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);
111 fsync(fd);
113 close(fd);
115 printf("Swapspace size: %luk\n", pages*(unsigned long)(pagesize/1024));
116 return 0;