#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include "../src/alf.h"
#include <errno.h>
#ifdef MS_WIN32
#include <io.h>
#include <direct.h>
#define L "I64"
#define STDERR stdout
#else
#include <unistd.h>
#include <dirent.h>
#define L "L"
#define STDERR stderr
#endif
#ifdef DMALLOC
#include "dmalloc.h"
#endif
#define DIM(a) (sizeof(a)/sizeof(a[0]))
#ifdef MS_WIN32
#define getcwd _getcwd
#endif
void
zapdir(const char *directory) {
#ifndef MS_WIN32
/* this is not portable! relies on GNU getcwd semantics! */
char *cwd = getcwd (NULL, 0);
DIR *dir;
struct dirent *entry;
if (chdir(directory) == -1) {
free(cwd);
return;
}
dir = opendir(".");
entry = readdir(dir);
while (entry != NULL) {
if (entry->d_name[0] == '.')
if (entry->d_name[1] == '\0' ||
(entry->d_name[1] == '.' && entry->d_name[2] == '\0'))
goto next;
unlink(entry->d_name);
next:
entry = readdir(dir);
}
closedir(dir);
chdir(cwd);
rmdir(directory);
free(cwd);
#else
char cwd [255];
char * filepattern = NULL;
HANDLE hFindFile;
WIN32_FIND_DATA FileData;
BOOL status;
filepattern = malloc(strlen(directory)+40);
GetCurrentDirectory (255, cwd);
if (SetCurrentDirectory(directory) == 0) {
return;
}
strcpy(filepattern, directory);
strcat(filepattern, "\\*");
hFindFile = FindFirstFile (filepattern, &FileData);
status = hFindFile != INVALID_HANDLE_VALUE;
while (status) {
if (FileData.cFileName [0] == '.')
if ( FileData.cFileName [1] == '\0'
|| ( FileData.cFileName [1] == '.'
&& FileData.cFileName [2] == '\0'
)
)
goto next;
DeleteFile (FileData.cFileName);
next:
status = FindNextFile (hFindFile, &FileData);
}
FindClose (hFindFile);
SetCurrentDirectory (cwd);
RemoveDirectory (directory);
#endif
}
#if 0
#define MAXBYTESIO 100000
static void
myfprintf(FILE *out, const char *fmt,
LONG_LONG a1, LONG_LONG a2, LONG_LONG a3, LONG_LONG a4, LONG_LONG a5) {
char buf[1000];
static unsigned int bytesprinted = 0;
static time_t starttime = (time_t)0;
if (starttime == (time_t)0)
starttime = time(0);
else {
if (time(0)-starttime > (time_t)10) {
fprintf(STDERR, "Too much time\n");
exit(1);
}
};
sprintf(buf, fmt, a1, a2, a3, a4, a5);
bytesprinted += strlen(buf);
if (bytesprinted > MAXBYTESIO) {
fprintf(STDERR, "Too much I/O\n");
exit(1);
}
fprintf(out, buf);
}
static void
myprintf(const char *fmt, int a1, int a2, int a3, int a4, int a5) {
myfprintf(stdout, fmt, a1, a2, a3, a4, a5);
}
#define print0(fmt) myprintf(fmt,0,0,0,0,0)
#define print1(fmt,a) myprintf(fmt,a,0,0,0,0)
#define print2(fmt,a,b) myprintf(fmt,a,b,0,0,0)
#define print3(fmt,a,b,c) myprintf(fmt,a,b,c,0,0)
#define print4(fmt,a,b,c,d) myprintf(fmt,a,b,c,d,0)
#define print5(fmt,a,b,c,d,e) myprintf(fmt,a,b,c,d,e)
#define fprint0(out,fmt) myfprintf(out,fmt,0,0,0,0,0)
#define fprint1(out,fmt,a) myfprintf(out,fmt,a,0,0,0,0)
#define fprint2(out,fmt,a,b) myfprintf(out,fmt,a,b,0,0,0)
#define fprint3(out,fmt,a,b,c) myfprintf(out,fmt,a,b,c,0,0)
#define fprint4(out,fmt,a,b,c,d) myfprintf(out,fmt,a,b,c,d,0)
#define fprint5(out,fmt,a,b,c,d,e) myfprintf(out,fmt,a,b,c,d,e)
#else
#define print0(fmt) printf(fmt)
#define print1(fmt,a) printf(fmt,a)
#define print2(fmt,a,b) printf(fmt,a,b)
#define print3(fmt,a,b,c) printf(fmt,a,b,c)
#define print4(fmt,a,b,c,d) printf(fmt,a,b,c,d)
#define print5(fmt,a,b,c,d,e) printf(fmt,a,b,c,d,e)
#define fprint0(out,fmt) fprintf(out,fmt)
#define fprint1(out,fmt,a) fprintf(out,fmt,a)
#define fprint2(out,fmt,a,b) fprintf(out,fmt,a,b)
#define fprint3(out,fmt,a,b,c) fprintf(out,fmt,a,b,c)
#define fprint4(out,fmt,a,b,c,d) fprintf(out,fmt,a,b,c,d)
#define fprint5(out,fmt,a,b,c,d,e) fprintf(out,fmt,a,b,c,d,e)
#endif
int
main (int argc, char **argv) {
ALF *f;
char *line = "here are some bytes\n";
char buf[1000];
char buf2[1000];
int nbytes;
#ifdef MS_WIN32
char *file1 = "p:\\skip\\alf\\foo1";
char *file2 = "p:\\skip\\alf\\foo2";
#else
char *file1 = "./foo1";
char *file2 = "./foo2";
#endif
unsigned char c;
unsigned int i;
unsigned LONG_LONG len;
int test = 0;
int ncalls;
#ifndef MS_WIN32
setvbuf(stderr, NULL, _IOLBF, 0);
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
/* possible clean up from previous run */
zapdir(file1);
zapdir(file2);
/****************************************************/
printf("%2d. supports large files? %2d\n",
++test, alf_supports_large_files());
/****************************************************/
print1("%2d. testing basic write and seek beyond EOF.\n", ++test);
f = alf_open(file1, "wb", 0);
if (f == NULL) {
fprint2(STDERR, "** open %s for write failed: %d.\n",
file1, errno);
return 1;
}
nbytes = alf_write(line, 1, strlen(line), f);
print1(" wrote: %2d bytes\n", nbytes);
if (alf_seek(f, 4000, SEEK_SET) == -1) {
fprint0(STDERR, "** seek to offset 4000 failed.\n");
return 1;
}
print2(" seeked to position %" L "d (chunk: %2d)\n", alf_tell(f),
f->current_chunk);
nbytes = alf_write(line, 1, strlen(line), f);
print1(" wrote: %2d bytes\n", nbytes);
alf_close(f);
/****************************************************/
print1("%2d. testing basic read.\n", ++test);
f = alf_open(file1, "r", 0);
if (f == NULL) {
fprint1(STDERR, "** open for read failed: %d.\n", errno);
return 1;
}
if (alf_seek(f, 0, SEEK_END) == -1) {
fprint1(STDERR, "** seek to end of file failed: %d.\n", errno);
return 1;
}
len = alf_tell(f);
nbytes = 0;
alf_rewind(f);
ncalls = 0;
while (alf_eof(f) == 0) {
print4(" nbytes: %d, len: %" L "d, feof: %d, alf_eof: %d,",
nbytes, len, feof(f->current), alf_eof(f));
print2(" chunks: (%d of %d).\n", f->current_chunk+1, f->nchunks);
if (feof(f->current) && f->current_chunk == f->nchunks-1) {
fprint0(STDERR, "** alf_eof reports not @ eof but feof does.\n");
return 1;
}
if (nbytes > len) {
fprint2(STDERR, "** past apparent eof (%d > %" L "d), but alf_eof"
" and feof reports not @ eof.\n", nbytes, len);
return 1;
}
nbytes += alf_read(buf, 1, DIM(buf)-1, f);
if (errno) {
fprint0(STDERR, "** errno set during alf_read.\n");
return 1;
}
if (ncalls++ > 50) {
fprint0(STDERR, "** alf_read loop should have ended by now.\n");
return 1;
}
}
print2(" reading to eof read %2d bytes. File has length %lld.\n",
nbytes, len);
alf_close(f);
/****************************************************/
print1("%2d. testing seek within file.\n", ++test);
f = alf_open(file1, "r", 0);
if (f == NULL) {
fprint1(STDERR, "** open for read failed: %d.\n", errno);
return 1;
}
if (alf_seek(f, 3950, SEEK_SET) == -1) {
fprint0(STDERR, "** seek to offset 3950 failed.\n");
return 1;
}
print2(" seeked to position %" L "d (chunk: %2d)\n", alf_tell(f),
f->current_chunk);
nbytes = alf_read(buf, 1, DIM(buf)-1, f);
buf[nbytes] = '\0';
print2(" read: %2d bytes: %s\n", nbytes, buf);
alf_close(f);
/****************************************************/
print1("%2d. testing r+ capability.\n", ++test);
f = alf_open(file1, "rb+", 0);
if (f == NULL) {
fprint1(STDERR, "** open for rb+ failed: %d.\n", errno);
return 1;
}
if (alf_seek(f, 3950, SEEK_SET) == -1) {
fprint0(STDERR, "** seek to offset 3950 failed.\n");
return 1;
}
print2(" seeked to position %" L "d (chunk: %2d)\n", alf_tell(f),
f->current_chunk);
nbytes = alf_write(line, 1, strlen(line), f);
nbytes += alf_write(line, 1, strlen(line), f);
nbytes += alf_write(line, 1, strlen(line), f);
print1(" wrote: %2d bytes\n", nbytes);
if (alf_seek(f, -nbytes, SEEK_CUR) == -1) {
fprint1(STDERR, "** seek to offset %2d from current pos failed.\n",
-nbytes);
return 1;
}
print2(" seeked to position %" L "d (chunk: %2d)\n", alf_tell(f),
f->current_chunk);
if ((nbytes = alf_read(buf, 1, strlen(line), f)) != (int)strlen(line)) {
fprint0(STDERR, "** read after seek failed.\n");
return 1;
}
buf[nbytes] = '\0';
if (strncmp(line, buf, strlen(line)) != 0) {
fprint2(STDERR, "** read after seek got wrong data: %s != %s\n",
buf, line);
return 1;
}
for (i=0; i<10; i++) {
for (c=0; c<128; c+=2)
if (alf_putc(c, f) == EOF) {
fprint1(STDERR, "** alf_putc of %c failed.\n", c);
return 1;
}
}
alf_close(f);
/****************************************************/
print1("%2d. testing append mode.\n", ++test);
f = alf_open(file1, "a", 0);
if (f == NULL) {
fprint1(STDERR, "** open for append failed: %d.\n", errno);
return 1;
}
nbytes = alf_write(line, 1, strlen(line), f);
print1(" wrote: %2d bytes\n", nbytes);
if (alf_seek(f, LONG32_MAX+(LONG_LONG)5000, SEEK_SET) == -1) {
fprint1(STDERR, "** seek to offset %" L "d failed.\n",
LONG32_MAX+(LONG_LONG)5000);
return 1;
}
print2(" seeked to position %" L "d (chunk: %2d)\n", alf_tell(f),
f->current_chunk);
nbytes = alf_write(line, 1, strlen(line), f);
print1(" wrote: %2d bytes\n", nbytes);
if (alf_seek(f, LONG32_MAX-(LONG_LONG)5000, SEEK_SET) == -1) {
fprint1(STDERR, "** seek to offset %" L "d failed.\n",
LONG32_MAX-(LONG_LONG)5000);
return 1;
}
print2(" seeked to position %" L "d (chunk: %2d)\n", alf_tell(f),
f->current_chunk);
for (i=0; i<10; i++) {
for (c=0; c<128; c+=2)
if (alf_putc(c, f) == EOF) {
fprint1(STDERR, "** alf_putc of %c failed.\n", c);
return 1;
}
}
alf_close(f);
/****************************************************/
#ifndef MS_WIN32
print1("%2d. testing open of non-ALF file for read.\n", ++test);
f = alf_open("/etc/hosts", "r", 0);
if (f != NULL) {
alf_close(f);
fprint0(STDERR,
"** open of /etc/hosts should not have succeeded.\n");
return 1;
}
/****************************************************/
print1("%2d. testing open of read-only ALF file.\n", ++test);
chmod(file1, 0555);
f = alf_open(file1, "r", 0);
if (f == NULL) {
fprint1(STDERR, "** open for read of read-only file failed: %d.\n",
errno);
return 1;
}
else {
nbytes = alf_read(buf, 1, 10, f);
buf[nbytes] = '\0';
print1(" read: %2d bytes\n", nbytes);
alf_rewind(f);
if ((int)alf_read(buf2, 1, 10, f) != nbytes) {
fprint0(STDERR, "** read after rewind not the same.\n");
return 1;
}
else {
for (i=0; i<10; i++) {
if (buf[i] != buf2[i]) {
fprint0(STDERR, "** read after rewind not the same.\n");
return 1;
}
}
}
print1(" truncating from %lld to 10\n", f->length);
if (alf_truncate(f, 10) != -1) {
fprint0(STDERR,
"** truncate of read-only file succeeded spuriously.\n");
return 1;
}
alf_close(f);
}
/****************************************************/
print1("%2d. testing append mode open of read-only ALF file.\n", ++test);
f = alf_open(file1, "a", 0);
if (f != NULL) {
alf_close(f);
fprint0(STDERR, "** open for append of read-only file"
" should not have succeeded.\n");
return 1;
}
/****************************************************/
print1("%2d. testing open of read-protected ALF file.\n", ++test);
chmod(file1, 0055);
f = alf_open(file1, "r", 0);
if (f != NULL) {
alf_close(f);
fprint0(STDERR, "open for read of read-protected file"
" should not have succeeded.\n");
return 1;
}
chmod(file1, 0755);
/****************************************************/
print1("%2d. testing alf_reopen.\n", ++test);
f = alf_open(file1, "r", 0);
if (f == NULL) {
fprint1(STDERR, "** open for write failed: %d.\n", errno);
return 1;
}
f = alf_reopen(file2, "w", 0, f);
if (f == NULL) {
fprint1(STDERR, "** reopen from foo to foo2 failed: %d.\n", errno);
return 1;
}
else
alf_close(f);
/****************************************************/
print1("%2d. testing long seeks, truncation, and alf_puts.\n", ++test);
f = alf_open(file1, "w", 0);
if (f == NULL) {
fprint1(STDERR, "** open for write failed: %d.\n", errno);
return 1;
}
for (i=0; i<10; i++) {
if (alf_write("abc", 1, 3, f) != 3) {
fprint1(STDERR, "** write failed: %d.\n", errno);
return 1;
}
if (alf_seek(f, (i+1)*(LONG_LONG)LONG32_MAX, SEEK_SET) == -1) {
fprint0(STDERR, "** seek failed.\n");
return 1;
}
}
print1(" truncating from %lld to 3000\n", f->length);
if (alf_truncate(f, 3000) == -1) {
fprint0(STDERR, "** truncate failed.\n");
return 1;
}
alf_puts("abc", f);
alf_puts("", f);
alf_close(f);
/****************************************************/
print1("%2d. testing write mode on existing file\n", ++test);
f = alf_open(file1, "w", 0);
if (f == NULL) {
fprint1(STDERR, "** open for write failed: %d.\n", errno);
return 1;
}
if (alf_write("1234567890", 1, 10, f) != 10) {
fprint0(STDERR, "** create/write failed.\n");
return 1;
}
alf_close(f);
/****************************************************/
print1("%2d. testing append mode on existing file\n", ++test);
f = alf_open(file1, "a", 0);
if (f == NULL) {
fprint1(STDERR, "** open for append failed: %d.\n", errno);
return 1;
}
if (alf_seek(f, 3, SEEK_SET) == -1) {
fprint0(STDERR, "** seek failed.\n");
return 1;
}
if (alf_write("abc", 1, 3, f) != 3) {
fprint0(STDERR, "** write in append mode failed.\n");
return 1;
}
alf_close(f);
print1("%2d. reading back bytes written during append mode\n", ++test);
f = alf_open(file1, "r", 0);
if (f == NULL) {
fprint1(STDERR, "** open for read failed: %d.\n", errno);
return 1;
}
nbytes = alf_read(buf, 1, DIM(buf)-1, f);
if (nbytes != 13) {
fprint0(STDERR, "** failed to read all 13 bytes from file.\n");
return 1;
}
alf_close(f);
buf[nbytes] = '\0';
if (strcmp("1234567890abc", buf) != 0) {
fprint1(STDERR, "** failed to get expected contents: %s\n", buf);
return 1;
}
/****************************************************/
print1("%2d. testing alf_flush, read across multiple chunks, "
"read of writable file\n", ++test);
f = alf_open(file1, "w", 0);
if (f == NULL) {
fprint0(STDERR, "** create failed.\n");
return 1;
}
if (alf_read(buf, 1, 1, f) != 0) {
fprint0(STDERR, "** read in write mode succeeded spuriously.\n");
return 1;
}
alf_clearerr(f);
if (alf_write("123\0", 1, 4, f) != 4) {
fprint0(STDERR, "** write failed.\n");
return 1;
}
if (alf_seek(f, 10, SEEK_SET) == -1) {
fprint0(STDERR, "** seek failed.\n");
return 1;
}
if (alf_write("456\0", 1, 4, f) != 4) {
fprint0(STDERR, "** write failed.\n");
return 1;
}
if (alf_seek(f, 20, SEEK_SET) == -1) {
fprint0(STDERR, "** seek failed.\n");
return 1;
}
if (alf_write("789\0", 1, 4, f) != 4) {
fprint0(STDERR, "** write failed.\n");
return 1;
}
if (alf_seek(f, 30, SEEK_SET) == -1) {
fprint0(STDERR, "** seek failed.\n");
return 1;
}
if (alf_write("ABC\0", 1, 4, f) != 4) {
fprint0(STDERR, "** write failed.\n");
return 1;
}
if (alf_flush(f) == -1) {
fprint0(STDERR, "** flush failed.\n");
return 1;
}
alf_close(f);
f = alf_open(file1, "r", 0);
if (f == NULL) {
fprint1(STDERR, "** open for read failed: %d.\n", errno);
return 1;
}
if (alf_read(buf, 1, 34, f) != 34) {
fprint0(STDERR, "** read failed.\n");
return 1;
}
if (alf_flush(f) != -1) {
fprint0(STDERR, "** flush succeeded spuriously.\n");
return 1;
}
if (strcmp(&buf[ 0], "123") != 0 ||
strcmp(&buf[10], "456") != 0 ||
strcmp(&buf[20], "789") != 0 ||
strcmp(&buf[30], "ABC") != 0) {
fprint0(STDERR, "** read didn't get correct data.\n");
return 1;
}
/****************************************************/
print1("%2d. testing write on file opened for read\n", ++test);
f = alf_open(file1, "r", 0);
if (f == NULL) {
fprint1(STDERR, "** open for read failed: %d.\n", errno);
return 1;
}
if (alf_write("XXX", 1, 3, f) != 0) {
fprint0(STDERR, "** write in read mode succeeded spuriously.\n");
return 1;
}
if (alf_error(f) == 0) {
fprint0(STDERR, "** error flag not set after write error.\n");
return 1;
}
alf_clearerr(f);
if (alf_putc('d', f) != -1) {
fprint0(STDERR, "** write in read mode succeeded spuriously.\n");
return 1;
}
alf_clearerr(f);
alf_close(f);
#endif
return 0;
}
/*
* Local Variables: ***
* c-basic-offset: 4 ***
* indent-tabs-mode: nil ***
* End: ***
*/
syntax highlighted by Code2HTML, v. 0.9.1