am 16068830: Merge "toolbox: enable mkswap to work on block devices"

* commit '16068830444361ab65cbc9804b76e2d415aff9a2':
  toolbox: enable mkswap to work on block devices
This commit is contained in:
Elliott Hughes 2014-11-18 19:19:49 +00:00 committed by Android Git Automerger
commit 450c4ad097

View file

@ -1,11 +1,13 @@
#include <fcntl.h>
#include <linux/fs.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h>
#include <sys/swap.h> #include <sys/swap.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/* XXX This needs to be obtained from kernel headers. See b/9336527 */ /* This is not in a uapi header. */
struct linux_swap_header { struct linux_swap_header {
char bootbits[1024]; /* Space for disklabel etc. */ char bootbits[1024]; /* Space for disklabel etc. */
uint32_t version; uint32_t version;
@ -23,71 +25,67 @@ struct linux_swap_header {
int mkswap_main(int argc, char **argv) int mkswap_main(int argc, char **argv)
{ {
int err = 0;
int fd;
ssize_t len;
off_t swap_size;
int pagesize;
struct linux_swap_header sw_hdr;
if (argc != 2) { if (argc != 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]); fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return -EINVAL; return EXIT_FAILURE;
} }
fd = open(argv[1], O_WRONLY); int fd = open(argv[1], O_RDWR);
if (fd < 0) { if (fd < 0) {
err = errno; fprintf(stderr, "Cannot open %s: %s\n", argv[1], strerror(errno));
fprintf(stderr, "Cannot open %s\n", argv[1]); return EXIT_FAILURE;
return err;
} }
pagesize = getpagesize();
/* Determine the length of the swap file */ /* Determine the length of the swap file */
swap_size = lseek(fd, 0, SEEK_END); off64_t swap_size;
if (swap_size < MIN_PAGES * pagesize) { struct stat sb;
fprintf(stderr, "Swap file needs to be at least %dkB\n", if (fstat(fd, &sb)) {
(MIN_PAGES * pagesize) >> 10); fprintf(stderr, "Couldn't fstat file: %s\n", strerror(errno));
err = -ENOSPC; return EXIT_FAILURE;
goto err;
} }
if (lseek(fd, 0, SEEK_SET)) { if (S_ISBLK(sb.st_mode)) {
err = errno; if (ioctl(fd, BLKGETSIZE64, &swap_size) < 0) {
fprintf(stderr, "Can't seek to the beginning of the file\n"); fprintf(stderr, "Couldn't determine block device size: %s\n", strerror(errno));
goto err; return EXIT_FAILURE;
}
} else {
swap_size = sb.st_size;
} }
int pagesize = getpagesize();
if (swap_size < MIN_PAGES * pagesize) {
fprintf(stderr, "Swap file needs to be at least %d KiB\n", (MIN_PAGES * pagesize) >> 10);
return EXIT_FAILURE;
}
struct linux_swap_header sw_hdr;
memset(&sw_hdr, 0, sizeof(sw_hdr)); memset(&sw_hdr, 0, sizeof(sw_hdr));
sw_hdr.version = 1; sw_hdr.version = 1;
sw_hdr.last_page = (swap_size / pagesize) - 1; sw_hdr.last_page = (swap_size / pagesize) - 1;
len = write(fd, &sw_hdr, sizeof(sw_hdr)); ssize_t len = write(fd, &sw_hdr, sizeof(sw_hdr));
if (len != sizeof(sw_hdr)) { if (len != sizeof(sw_hdr)) {
err = errno; fprintf(stderr, "Failed to write swap header into %s: %s\n", argv[1], strerror(errno));
fprintf(stderr, "Failed to write swap header into %s\n", argv[1]); return EXIT_FAILURE;
goto err;
} }
/* Write the magic header */ /* Write the magic header */
if (lseek(fd, pagesize - MAGIC_SWAP_HEADER_LEN, SEEK_SET) < 0) { if (lseek(fd, pagesize - MAGIC_SWAP_HEADER_LEN, SEEK_SET) < 0) {
err = errno; fprintf(stderr, "Failed to seek into %s: %s\n", argv[1], strerror(errno));
fprintf(stderr, "Failed to seek into %s\n", argv[1]); return EXIT_FAILURE;
goto err;
} }
len = write(fd, MAGIC_SWAP_HEADER, MAGIC_SWAP_HEADER_LEN); len = write(fd, MAGIC_SWAP_HEADER, MAGIC_SWAP_HEADER_LEN);
if (len != MAGIC_SWAP_HEADER_LEN) { if (len != MAGIC_SWAP_HEADER_LEN) {
err = errno; fprintf(stderr, "Failed to write magic swap header into %s: %s\n", argv[1], strerror(errno));
fprintf(stderr, "Failed to write magic swap header into %s\n", argv[1]); return EXIT_FAILURE;
goto err;
} }
if (fsync(fd) < 0) { if (fsync(fd) < 0) {
err = errno; fprintf(stderr, "Failed to sync %s: %s\n", argv[1], strerror(errno));
fprintf(stderr, "Failed to sync %s\n", argv[1]); return EXIT_FAILURE;
goto err;
} }
err:
close(fd); close(fd);
return err; return EXIT_SUCCESS;
} }