#include <stdio.h>
#include <stdlib.h>
#include <sys/disk.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#define DOSBOOTBLOCKSIZE 512
#define MAX_SECTOR_SIZE 4096
#define E_OPENDEV -1
#define E_READ -5
void usage(void);
char *rawname(char *name);
char *unrawname(char *name);
int checkVolHdr(const unsigned char *volhdr);
char *blockcheck(char *origname);
char *progname;
int
main(int argc, char **argv)
{
unsigned char volhdr[MAX_SECTOR_SIZE] = {0};
int fd, retval;
char *devname;
fd = -1;
retval = 0;
if ((progname = strrchr(*argv, '/')))
++progname;
else
progname = *argv;
if (argc != 2) {
usage();
} else {
devname = blockcheck(argv[1]);
if (devname != NULL) {
if ((fd = open(devname, O_RDONLY, 0)) < 0) {
retval = E_OPENDEV;
} else if (read(fd, volhdr, MAX_SECTOR_SIZE) != MAX_SECTOR_SIZE) {
retval = E_READ;
} else {
retval = checkVolHdr(volhdr);
}
if (-1 != fd) {
close(fd);
fd = -1;
}
}
}
return retval;
}
void
usage(void)
{
fprintf(stdout, "usage: %s device\n", progname);
return;
}
char *
rawname(char *name)
{
static char rawbuf[32];
char *dp;
if ((dp = strrchr(name, '/')) == 0)
return (0);
*dp = 0;
(void) strlcpy(rawbuf, name, sizeof(rawbuf));
*dp = '/';
(void) strlcat(rawbuf, "/r", sizeof(rawbuf));
(void) strlcat(rawbuf, &dp[1], sizeof(rawbuf));
return (rawbuf);
}
char *
unrawname(char *name)
{
char *dp;
struct stat stb;
size_t dp_len;
if ((dp = strrchr(name, '/')) == 0)
return (name);
if (stat(name, &stb) < 0)
return (name);
if ((stb.st_mode & S_IFMT) != S_IFCHR)
return (name);
if (dp[1] != 'r')
return (name);
dp_len = strlen(&dp[2]) + 1;
(void)memmove(&dp[1], &dp[2], dp_len);
return (name);
}
char *
blockcheck(char *origname)
{
struct stat stblock, stchar;
char *newname, *raw;
int retried;
retried = 0;
newname = origname;
retry:
if (stat(newname, &stblock) < 0) {
perror(newname);
fprintf(stderr, "Can't stat %s\n", newname);
return NULL;
}
if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
raw = rawname(newname);
if (stat(raw, &stchar) < 0) {
perror(raw);
fprintf(stderr, "Can't stat %s\n", raw);
return NULL;
}
if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
return (raw);
} else {
fprintf(stderr, "%s is not a character device\n", raw);
return NULL;
}
} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
newname = unrawname(newname);
retried++;
goto retry;
}
return NULL;
}
int
checkVolHdr(const unsigned char *volhdr)
{
const char *ntfs_oemid = "NTFS ";
int retval;
retval = 1;
if (memcmp(ntfs_oemid, volhdr + 3, 8))
retval = 0;
return retval;
}