#include <sys/stat.h>
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define E_OPENDEV -1
#define E_READ -5
void usage(void);
char *rawname(char *name);
char *unrawname(char *name);
int checkVolHdr(const struct fs *volhdr);
char *blockcheck(char *origname);
char *progname;
int
main(int argc, char **argv)
{
union {
struct fs fs;
char pad[SBSIZE];
} volhdr;
char *devname = NULL;
int fd, retval;
retval = 0;
fd = -1;
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 (pread(fd, &(volhdr.fs), SBSIZE, (off_t) SBOFF) != SBSIZE) {
retval = E_READ;
} else {
retval = checkVolHdr(&(volhdr.fs));
}
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) strcpy(rawbuf, name);
*dp = '/';
(void) strcat(rawbuf, "/r");
(void) strcat(rawbuf, &dp[1]);
return (rawbuf);
}
char *
unrawname(char *name)
{
char *dp;
struct stat stb;
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);
(void) strcpy(&dp[1], &dp[2]);
return (name);
}
char *
blockcheck(char *origname)
{
struct stat stblock, stchar;
char *newname, *raw;
int 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 struct fs * volhdr)
{
int retval = 0;
retval = (volhdr->fs_magic == FS_MAGIC);
return retval;
}