1
0
Files
2022-09-29 17:59:04 +03:00

272 lines
5.5 KiB
C

/*
* rdwr.c -- Another disk test program.
*
* This disk test will read a specified portion of a disk or file once.
* It will then write and read the file (according to options) until
* it gets an error. Any writing done will write out what was read in
* originally, so the test is non-destructive. It should not be run
* on the block or character device corresponding to a mounted file
* system, therefore, since it will re-write the data that it read
* in originally.
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
char * pname;
char * buf1;
char * buf2;
int readonly = 0;
void usage(char *name);
extern int errno;
main(argc, argv)
int argc;
char *argv[];
{
register int size = 0;
register int rwsize = BBSIZE;
register int niterations = 1;
register int lsize, seekpoint;
char * fname = NULL;
struct stat sbuf;
int c, fd, debug;
int id = getpid();
extern int optind;
extern char * optarg;
char * malloc();
pname = argv[0];
while ((c=getopt(argc, argv, "drf:s:i:b:")) != EOF) {
switch (c) {
case 'r':
readonly = 1;
continue;
case 'd':
debug = 1;
continue;
case 's':
size = strtol(optarg, 0, 0);
while (size & (BBSIZE-1))
size--;
if (debug)
fprintf(stderr, "size set to %d (0x%x)\n",
size, size);
/* argc--; */
continue;
case 'b':
rwsize = strtol(optarg, 0, 0);
while (rwsize & (BBSIZE-1))
rwsize--;
if (debug)
fprintf(stderr, "rwsize max set to %d (0x%x)\n",
rwsize, rwsize);
/* argc--; */
continue;
case 'i':
niterations = strtol(optarg, 0, 0);
if (debug)
fprintf(stderr, "niterations set to %d\n",
niterations);
/* argc--; */
continue;
case 'f':
fname = optarg;
if (debug)
fprintf(stderr, "file is %s\n", fname);
/* argc--; */
continue;
}
}
if (fname == NULL) {
usage(pname);
exit(1);
}
if (stat(pname, &sbuf)) {
perror("stat");
exit(1);
}
/*
if (sbuf.st_size < size || size == 0) {
size = sbuf.st_size;
if (size || debug)
fprintf(stderr, "WARNING: %s setting size to %d\n",
pname, size);
while (size & (BBSIZE-1))
size--;
}
*/
if (size == 0 || rwsize == 0) {
fprintf(stderr, "%s: ERROR: 0 size!\n", pname);
exit(1);
}
fd = open(fname, O_RDWR);
if (fd < 0) {
fprintf(stderr, "%s: ERROR: device open failed\n", pname);
perror("open");
exit(1);
}
buf1 = malloc(size+rwsize);
buf2 = malloc(size+rwsize);
if (!buf1 || !buf2) {
fprintf(stderr, "%s: ERROR: malloc failed\n", pname);
exit(1);
}
c = size+rwsize;
if (read(fd, buf1, c) != c) {
fprintf(stderr, "%s: ERROR: unable to read copy 1\n", pname);
exit(1);
}
srandom(time(0));
while (--niterations >= 0) {
seekpoint = (random() % size + 256) & ~(BBSIZE - 1);
lsize = (random() % rwsize + 512) & ~(BBSIZE - 1);
if (lseek(fd, seekpoint, SEEK_SET) < 0) {
fprintf(stderr, "%s: ERROR: seekpoint at %d (0x%x)\n",
pname, seekpoint, seekpoint);
perror("lseek");
exit(1);
}
if (readonly || (random() % 4) == 0) {
/*
* Read
*/
if (debug) {
fprintf(stderr, "(%d: rd %x,%x) ",
id, seekpoint, lsize);
}
if ((c = read(fd, buf2 + seekpoint, lsize)) != lsize) {
fprintf(stderr,
"%s: ERROR: short read of 0x%x at 0x%x,0x%x!\n",
pname, c, seekpoint, lsize);
if (errno)
perror("read");
exit(1);
}
if (compare(seekpoint, lsize, 0)) {
if (lseek(fd, seekpoint, SEEK_SET) < 0) {
fprintf(stderr,
"%s: ERROR: seekpoint at %d (0x%x)\n",
pname, seekpoint, seekpoint);
perror("lseek");
exit(1);
}
if ((c = read(fd, buf2 + seekpoint, lsize)) != lsize) {
fprintf(stderr,
"%s: ERROR: short read of 0x%x at 0x%x,0x%x!\n",
pname, c, seekpoint, lsize);
if (errno)
perror("read");
exit(1);
}
compare(seekpoint, lsize, 1);
}
} else {
/*
* Write
*/
if (debug) {
fprintf(stderr, "(%d: wr %x,%x) ",
id, seekpoint, lsize);
}
if ((c = write(fd, buf1 + seekpoint, lsize)) != lsize) {
fprintf(stderr,
"%s: ERROR: short write of 0x%x at 0x%x,0x%x!\n",
pname, c, seekpoint, lsize);
if (errno)
perror("write");
exit(1);
}
}
}
}
int nzero;
int nones;
void
comparebits(c1, c2)
register unsigned char c1, c2;
{
while (c1 || c2) {
if ((c1 & 1) && !(c2 & 1))
nzero++;
else if ((c2 & 1) && !(c1 & 1))
nones++;
c1 >>= 1, c2 >>= 1;
}
}
compare(seekpt, sz, exit_on_fail)
{
register unsigned char *p1, *p2;
register int nerrors;
nzero = nones = 0;
p1 = (unsigned char *) buf1 + seekpt;
p2 = (unsigned char *) buf2 + seekpt;
if (memcmp(p1, p2, sz) == 0)
return 0;
fprintf(stderr, "%s: ERROR: time=%ld, try #%d, addr 0x%x count 0x%x\n ",
pname, (long) time(0), exit_on_fail+1, seekpt, sz);
if (memcmp(p1, p2, sz) == 0) {
fprintf(stderr,
"%s: ERROR: first memcmp found miscompare; second didn't\n",
pname);
return 0;
}
while (--sz >= 0) {
if (*p1++ != *p2++) {
nerrors = 1;
fprintf(stderr, "%s: ERROR: error at 0x%x", pname, seekpt);
fprintf(stderr, " %x %x;", *(p1-1), *(p2-1));
comparebits(*(p1-1), *(p2-1));
while (--sz >= 0 && *p1 != *p2) {
nerrors++;
fprintf(stderr, " %x %x;", *p1, *p2);
comparebits(*p1, *p2);
p1++, p2++;
}
fprintf(stderr, " 0x%x bits went 0, 0x%x went 1\n",
nzero, nones);
if (exit_on_fail)
exit(1);
else
return(1);
}
seekpt++;
}
return 0;
}
void
usage(char *name)
{
fprintf(stderr,
"Usage: %s [-d] [-r] [-s size] [-i niterations] [-b rwsize ] -f file\n",
name);
}