int LZ77_Decompress( UINT8* inBuf, int inSize, UINT8* outBuf, int outSize, WRITE_MEMORY_FUNCT writeMem, READ_MEMORY_FUNCT readMem) { UINT8* inBufEnd = inBuf + inSize; UINT8* outBufEnd = outBuf + outSize; int counter; int currPos = 0; UINT8 window[ WINSIZE ]; for(counter = 0; counter < WINSIZE; counter ++) { window[ counter ] = ' '; } //#define CHECKEDREAD(x) if(inBuf >= inBufEnd ) { DebugBreak(); return -1; } x //#define CHECKEDWRITE(x) if(outBuf >= outBufEnd) { DebugBreak(); return -1; } x #define CHECKEDREAD(x,y) if(inBuf >= inBufEnd ) return -1; if(readMem != NULL) readMem ( (UINT32)y, 1, &x ); else x = *y #define CHECKEDWRITE(x,y) if(outBuf >= outBufEnd) return -1; if(writeMem != NULL) writeMem( (UINT32)x, 1, &y ); else *x = y while(inBuf < inBufEnd) { // // Get BitMap and data following it. // UINT8 bitMap; CHECKEDREAD(bitMap, inBuf++); // // Go through and decode data. // for(counter = 0; counter < 8 && outBuf < outBufEnd; counter++) { // // It's a code, so decode it and copy the data. // if(!BITSET(bitMap, counter)) { UINT8 byte1; UINT8 byte2; CHECKEDREAD(byte1, inBuf++); CHECKEDREAD(byte2, inBuf++); int length = LENGTH(byte2); int offset = OFFSET(byte1, byte2); // // Copy data from window. // while(length) { byte1 = window[ FAKE2REAL_POS(offset) ]; window[ FAKE2REAL_POS(currPos) ] = byte1; CHECKEDWRITE(outBuf++, byte1); currPos++; offset++; length--; } } else { UINT8 byte1; CHECKEDREAD(byte1, inBuf++); window[ FAKE2REAL_POS(currPos) ] = byte1; CHECKEDWRITE(outBuf++, byte1); currPos++; } } } #undef CHECKEDREAD #undef CHECKEDWRITE return 1; }
int main(int argc, char **argv) { int fifo = -1; int nfd = 0; int writepipe[2] = {-1}; int readpipe[2] = {-1}; struct passwd *pwent = NULL; pid_t child = -1; fd_set rfds; pwent = getpwuid(getuid()); if (!pwent || !pwent->pw_dir || !pwent->pw_dir[0]) return perror("pwent"), EXIT_FAILURE; strncpy(path, pwent->pw_dir, PATH_MAX); strncat(path, "/.sam.fifo", PATH_MAX); if (pipe(writepipe) != 0 || pipe(readpipe) != 0) return perror("pipe"), EXIT_FAILURE; unlink(path); if (mkfifo(path, 0600) != 0) return perror("mkfifo"), EXIT_FAILURE; atexit(cleanup); fifo = open(path, O_RDWR); if (fifo < 0) return perror("open"), EXIT_FAILURE; child = fork(); if (child == 0){ close(PARENT_WRITE); close(PARENT_READ); dup2(CHILD_READ, STDIN_FILENO); close(CHILD_READ); dup2(CHILD_WRITE, STDOUT_FILENO); close(CHILD_WRITE); execlp("sam", "sam", "-R", NULL); return EXIT_FAILURE; } else if (child < 0){ perror("fork"); return EXIT_FAILURE; } close(CHILD_READ); close(CHILD_WRITE); FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); FD_SET(fifo, &rfds); FD_SET(PARENT_READ, &rfds); nfd = MAX(STDIN_FILENO, MAX(PARENT_READ, fifo)) + 1; while (select(nfd, &rfds, NULL, NULL, NULL) >= 0){ ssize_t count = 0; char buf[8192]; if (FD_ISSET(STDIN_FILENO, &rfds)){ count = read(STDIN_FILENO, buf, 8192); if (count <= 0) exit(EXIT_SUCCESS); CHECKEDWRITE(PARENT_WRITE, buf, count); } if (FD_ISSET(fifo, &rfds)){ memset(buf, 0, 256); count = read(fifo, buf, 253); if (count <= 0) exit(EXIT_SUCCESS); CHECKEDWRITE(STDOUT_FILENO, "\x19\xff\x00", 3); CHECKEDWRITE(STDOUT_FILENO, buf, 255); } if (FD_ISSET(PARENT_READ, &rfds)){ count = read(PARENT_READ, buf, 8192); if (count <= 0) exit(EXIT_SUCCESS); CHECKEDWRITE(STDOUT_FILENO, buf, count); } FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); FD_SET(fifo, &rfds); FD_SET(PARENT_READ, &rfds); } return EXIT_SUCCESS; }