/* Test 15 -> Checks the lseek functionality in the library
* 
**/

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <dlfcn.h>

#include <errno.h>
int errno;

int main()
{
   int fd1 = -1, fd2 = -1;
   int err;
   void * handle = NULL;
   char buf[4096];
   char new_buf[4096];
   off_t cur=0;
   int i=0;
   int data_read = 0;
   off_t cur_new = 0;

    handle = dlopen("/lib/libc.so.6",  RTLD_LAZY);
    if (handle == NULL) {
	fprintf(stderr, "%s", dlerror());
	return -1;
    }
    int (*o_open)(const char *, int) = (int (*)(const char *, int)) dlsym(handle, "open");
    ssize_t (*o_read)(int, void *, size_t) = (ssize_t (*)(int, void *, size_t)) dlsym(handle, "read");
    ssize_t (*o_write)(int, void *, size_t) = (ssize_t (*)(int, void *, size_t)) dlsym(handle, "write");
    off_t (*o_lseek)(int, off_t, int) = (off_t (*)(int, off_t, int)) dlsym(handle, "lseek");
    int (*o_close)(int) = (int (*)(int)) dlsym(handle, "close");


/* Open the file with libfsprotect.c */
   fd1 = open("file5", O_RDONLY);
   if(fd1 == -1) {
         return -1;
   }

/* Open the file outside the library */
   fd2 = (*o_open)("file5",O_RDONLY);
   if(fd2 == -1) {
         close(fd1);
         return -1;
   }

   cur_new = (*o_lseek)(fd2, 4096, SEEK_SET);
   cur = lseek(fd1, 4096, SEEK_SET);
   if(cur != cur_new) {
        printf("lseek does not return the correct pointer %ld %ld\n", cur, cur_new);
        goto fail;
   }
   data_read = read(fd1, buf, 4096);
   data_read = (*o_read)(fd2, new_buf, 4096);
   if(memcmp(buf, new_buf, 4096) != 0) {
          goto fail;
   }   

   cur = lseek(fd1, 0, SEEK_END);
   cur_new = (*o_lseek)(fd2, 0, SEEK_END);
   if(cur != cur_new)
         goto fail;
 
   
   cur = lseek(fd1, cur-4096, SEEK_SET);
   cur_new = (*o_lseek)(fd2, cur_new-4096, SEEK_SET);
   if(cur != cur_new)
         goto fail;
   read(fd1, buf, 4096);
   (*o_read)(fd2, new_buf, 4096);
   if(memcmp(buf, new_buf, 4096) != 0) {
          goto fail;
   }   
   
pass:
   err = close(fd1);
   if(err == -1)
        return -1;
   (*o_close)(fd2);
   return 0;

fail:
   close(fd1);
   (*o_close)(fd2);
   return -1;

}
