/* Formats the given file for use by dm-csum */
/* Needed to use pwrite() and strtoll() */
#define _XOPEN_SOURCE 600
#include <stdio.h> /* printf() */
#include <stdlib.h> /* malloc() */
#include <unistd.h> /* pwrite() and friends */
#include <sys/types.h> /* open() */
#include <sys/stat.h> /* open() */
#include <fcntl.h> /* open() */
#include <stdint.h> /* uint8_t and friends */
#include <string.h> /* memset() */
/* simple definitions so we can copy-paste the structs from the kernel */
#define u8 uint8_t
#define __be16 uint16_t
#define __be32 uint32_t
/*
* Copied from the kernel definition, MUST match
*/
#define RESERVED_INITIAL_SECTORS_D 1
#define RESERVED_INITIAL_SECTORS_M 1
#define SECTORS_PER_IMD 62
struct imd_tuple {
__be16 crc;
__be16 flags;
__be32 tag;
} __attribute__ ((packed));
struct imd_sector_header {
u8 last_updated;
u8 unused1;
__be16 crc;
__be32 unused3;
} __attribute__ ((packed));
/* Format function to use when imd and data are on the same device */
int format_same(int fd, off_t total_size) {
int r;
off_t off;
unsigned char buf[1024];
struct imd_sector_header *m1, *m2;
memset(buf, 0, sizeof(buf));
m1 = (struct imd_sector_header *) buf;
m2 = (struct imd_sector_header *) (buf + 512);
m1->last_updated = 2;
m2->last_updated = 1;
off = RESERVED_INITIAL_SECTORS_D * 512;
while (off < total_size) {
r = pwrite(fd, buf, 1024, off);
if (r != 1024)
return -1;
off += 1024 + SECTORS_PER_IMD * 512;
}
return 0;
}
int format_diff(int data_fd, int imd_fd, off_t total_size)
{
printf("Not implemented yet\n");
return 0;
}
void usage()
{
printf("Use: mk-dm-csum same <device> [data length]\n");
printf(" or: mk-dm-csum diff <data device> <imd device> [data length]\n");
printf("\n");
printf("Note: data length is in bytes, and will be rounded down to\n");
printf("an appropriate bound.\n");
}
int main(int argc, char **argv)
{
int fd = -1, imd_fd = -1;
long long total_size;
int same;
if (argc < 3) {
usage();
return 1;
}
if (strcmp(argv[1], "same") == 0) {
same = 1;
} else if (strcmp(argv[1], "diff") == 0) {
/* TODO */
same = 0;
printf("Error: not implemented yet.\n");
return 1;
} else {
usage();
return 1;
}
fd = open(argv[2], O_WRONLY);
if (fd < 0) {
perror("Error opening device");
return 1;
}
if (argc >= 4) {
total_size = strtoll(argv[3], NULL, 0);
} else {
total_size = lseek(fd, 0, SEEK_END);
if (total_size == -1) {
perror("Error finding out the size");
return 1;
}
}
/* round down to a multiple of SECTORS_PER_IMD */
total_size -= total_size % SECTORS_PER_IMD;
printf("Effective total size: %llu\n", total_size);
if (same) {
if (format_same(fd, total_size) != 0) {
perror("Error formatting");
return 2;
}
} else {
if (format_diff(fd, imd_fd, total_size) != 0) {
perror("Error formatting");
return 2;
}
}
if (fsync(fd) != 0) {
perror("Error syncing data to disk");
return 3;
}
return 0;
}