#include #include #include #include #include #include #ifndef MAP_FILE # define MAP_FILE 0 #endif /* Define a generic cache facility for disk files. * * The goal is to be able to use mmap() to reduce the amount * of I/O performed. * * Using an internal cache is important when you're dealing with * files in small units (e.g. 32-byte "blocks"), or when you're * using a network file system. * * The cache routines return a pointer to the data, not a copy, * so if you run over the end of what you've asked for, you will * probably overwrite the next part of the file... probably. * This behaviour saves a *lot* of block copies. * You can change it by setting the CopyData flag; things will go * a lot slower, though. This might not actually be implemented. * */ typedef unsigned int t_BlockCacheFlag : 1; typedef struct s_LQU_BlockCacheEntry { struct s_LQU_BlockCacheEntry *Next; unsigned long Start; unsigned long Length; unsigned char *Data; t_BlockCacheFlag IsDirty; t_BlockCacheFlag IsLastInFile; t_BlockCacheFlag IsLockedForUpdate; t_BlockCacheFlag IsMapped; t_BlockCacheFlag CopyData; } t_LQU_BlockCacheEntry; typedef int (* LQU_BlockCacheCheckFunction) ( #ifdef HAVE_PROTO struct s_LQU_BlockCache *BlockCache, unsigned long ByteOffset, unsigned long Length, char *theData #endif ); typedef struct s_LQU_BlockCache { char *FileName; int fd; unsigned long LengthInBytes; t_LQU_BlockCacheEntry *BlockCacheEntryChain; int BytesPerBlock; int BlocksPerSegment; LQU_BlockCacheCheckFunction CheckBlockIsOKOnRead; LQU_BlockCacheCheckFunction CheckBlockIsOKOnWrite; t_BlockCacheFlag FileIsOpen; t_BlockCacheFlag FileIsOK; t_BlockCacheFlag WriteEnabled; t_BlockCacheFlag FileIsOK; } t_LQU_BlockCache; API t_LQU_BlockCache * LQU_OpenBlockCache( int Severity char *FileName char *What int FileMode, int FileProtectionMode, int BytesPerBlock int BlocksPerSegment LQU_BlockCacheCheckFunction CheckBlockIsOKOnRead; LQU_BlockCacheCheckFunction CheckBlockIsOKOnWrite; ) API char * LQU_GetBlock(cache, block, flags) API int LQU_DoneWithBlock(cache, block) int main(argc, argv) int argc; char *argv[]; { int fdin, fdout; char *src, *dst; struct stat statbuf; if (argc!=3) { fprintf(stderr, "bad boy, need 2 args (in, out)\b"); exit(27); } if ((fdin = open(argv[1], O_RDONLY)) < 0) { perror("input vomit"); exit(31); } if ((fdout = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) { fprintf(stderr, "output sodomy"); exit(119); } if (fstat(fdin, &statbuf) < 0) { perror("stat misthap"); exit(311); } /* set size of output file */ if (lseek(fdout, statbuf.st_size -1, SEEK_SET) < 0) { perror("seek him far and wide"); exit(7); } if (write(fdout, "", 1) != 1) { perror("write home again"); exit(19); } if ((src = mmap( 0, statbuf.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fdin, 0 )) == (caddr_t) -1) { perror("lost reading input"); exit(13); } if ((dst = mmap( 0, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fdout, 0 )) == (caddr_t) -1) { perror("lost my way"); exit(17); } memcpy(dst, src, statbuf.st_size); exit(0); }