#include #include #include #include #include #include "../src/alf.h" #include #ifdef MS_WIN32 #include #include #define L "I64" #define STDERR stdout #else #include #include #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: *** */