#include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
+
 
 #define MAX_FILES 256
 
 struct file_info {
     int size;
+    char filename[2048];
     char id[256];
-    char * data;
-    unsigned long long * offset_ptr;
 };
 
 int num_files = 0;
 struct file_info files[MAX_FILES];
 
+#define STDIO_FD 1
+
 
 int parse_config_input(ezxml_t cfg_input);
 int write_output(char * filename, ezxml_t cfg_output);
+int copy_file(int file_index, FILE * data_file);
 
 void usage() {
     printf("Usage: build_vm <infile> [-o outfile]\n");
     char * outfile = NULL;
     char * infile = NULL;
 
+
     memset((char *)files, 0, sizeof(files));
 
     opterr = 0;
     infile = argv[optind];
 
 
-    printf("Reading Input file: %s\n", infile);
+    printf("Input file: %s\n", infile);
 
     ezxml_t cfg_input = ezxml_parse_file(infile);
 
        return 1;
     }
 
-    printf("xml : %s\n", ezxml_toxml(cfg_input));
+    //  printf("xml : %s\n", ezxml_toxml(cfg_input));
 
 
 
 }
 
 
+
+int parse_config_input(ezxml_t cfg_input) {
+    ezxml_t file_tags = NULL;
+    ezxml_t tmp_file_tag = NULL;
+
+    // files are transformed into blobs that are slapped to the end of the file
+        
+    file_tags = ezxml_child(cfg_input, "files");
+
+    tmp_file_tag = ezxml_child(file_tags, "file");
+
+    while (tmp_file_tag) {
+       char * filename = get_val(tmp_file_tag, "filename");
+       struct stat file_stats;
+       char * id = get_val(tmp_file_tag, "id");
+       char index_buf[256];
+
+
+       if (stat(filename, &file_stats) != 0) {
+           perror(filename);
+           exit(-1);
+       }
+
+       files[num_files].size = (unsigned int)file_stats.st_size;
+       strncpy(files[num_files].id, id, 256);
+       strncpy(files[num_files].filename, filename, 2048);
+
+       snprintf(index_buf, 256, "%d", num_files);
+       ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
+
+       num_files++;
+       tmp_file_tag = ezxml_next(tmp_file_tag);
+    }
+
+
+    return 0;
+}
+
+
 int write_output(char * filename, ezxml_t cfg_output) {
     FILE * data_file = fopen(filename, "w+");
     char * new_cfg_str = ezxml_toxml(cfg_output);
     fwrite(&zero, 1, 8, data_file);
     offset += 8;
 
-    printf("setting number of files to %llu\n", file_cnt);
-    printf("sizeof(file_cnt)=%d \n", sizeof(file_cnt));
+    printf("Total number of files: %llu\n", file_cnt);
 
     fwrite(&file_cnt, 8, 1, data_file);
     offset += 8;
     fwrite(&zero, 1, 8, data_file);
 
     for (i = 0; i < num_files; i++) {
-       if (fwrite(files[i].data, 1, files[i].size, data_file) != files[i].size) {
-           printf("Error writing data file contents");
-           exit(-1);
-       }       
+
+       copy_file(i, data_file);
+       
     }
     
 
 }
 
 
+#define XFER_BLK_SIZE 4096
 
-int parse_config_input(ezxml_t cfg_input) {
-    ezxml_t file_tags = NULL;
-    ezxml_t tmp_file_tag = NULL;
+int copy_file(int file_index, FILE * data_file) {
+    char xfer_buf[XFER_BLK_SIZE];
+    int bytes_to_read = files[file_index].size;
+    int bytes_read = 0;
+    int xfer_len = XFER_BLK_SIZE;
+    FILE * in_file = NULL;
+    char * filename = files[file_index].filename;
+    struct winsize wsz;
+    char cons_line[256];
+    int prog_len = 0;
+    double ratio = 100;
+    int num_dots = 256;
 
-    // files are transformed into blobs that are slapped to the end of the file
-        
-    file_tags = ezxml_child(cfg_input, "files");
+    printf("Copying [%d] -- %s \n",
+          file_index,     
+          filename);
 
-    tmp_file_tag = ezxml_child(file_tags, "file");
 
-    while (tmp_file_tag) {
-       char * filename = get_val(tmp_file_tag, "filename");
-       struct stat file_stats;
-       FILE * data_file = NULL;
-       char * id = get_val(tmp_file_tag, "id");
-       char index_buf[256];
+    if (ioctl(STDIO_FD, TIOCGWINSZ, &wsz) == -1) {
+       printf("ioctl error on STDIO\n");
+       return -1;
+    }
 
-       snprintf(index_buf, 256, "%d", num_files);
 
+    memset(cons_line, 0, 256);
+    snprintf(cons_line, 256, "\r(%s) [", files[file_index].id);
+    prog_len = wsz.ws_col - (strlen(cons_line) + 11);
 
-       strncpy(files[num_files].id, ezxml_attr(tmp_file_tag, "id"), 256);
 
-       printf("file id=%s, name=%s\n", 
-              id,
-              filename);
-       
 
-       if (stat(filename, &file_stats) != 0) {
-           perror(filename);
-           exit(-1);
-       }
+    in_file = fopen(filename, "r");
 
-       files[num_files].size = (unsigned int)file_stats.st_size;
-       printf("file size = %d\n", files[num_files].size);
+    while (bytes_to_read > 0) {
+       struct winsize tmp_wsz;
+       int tmp_dots = 0;
 
-       files[num_files].data = malloc(files[num_files].size);
-
-       data_file = fopen(filename, "r");
+       if (ioctl(STDIO_FD, TIOCGWINSZ, &tmp_wsz) == -1) {
+           printf("ioctl error on STDIO\n");
+           return -1;
+       }
 
-       if (fread(files[num_files].data, files[num_files].size, 1, data_file) == 0) {
+       ratio = (double)bytes_read / (double)(files[file_index].size); 
+       tmp_dots = (int)(ratio * (double)prog_len);
+
+       if ((tmp_dots != num_dots) || (tmp_wsz.ws_col != wsz.ws_col)) {
+           int i = 0;
+           int num_blanks = 0;
+           
+           wsz = tmp_wsz;
+           num_dots = tmp_dots;
+           
+           num_blanks = prog_len - num_dots;
+
+           memset(cons_line, 0, 256);
+           snprintf(cons_line, 256, "\r(%s) [", files[file_index].id);
+           
+           for (i = 0; i < num_dots; i++) {
+               strcat(cons_line, "=");
+           }
+           
+           for (i = 0; i < num_blanks; i++) {
+               strcat(cons_line, " ");
+           }
+           
+           strcat(cons_line, "]");
+
+           //  printf("console width = %d\n", wsz.ws_col);
+           write(STDIO_FD, cons_line, wsz.ws_col);
+       }
+       
+       
+       
+       if (xfer_len > bytes_to_read) {
+           xfer_len = bytes_to_read;
+       }
+       
+       if (fread(xfer_buf, xfer_len, 1, in_file) == 0) {
            printf("Error reading data file %s\n", filename);
            exit(-1);
+       }       
+       
+       if (fwrite(xfer_buf, xfer_len, 1, data_file) == 0) {
+           printf("Error writing data file contents");
+           exit(-1);
        }
 
-       fclose(data_file);
 
+       bytes_read += xfer_len;
+       bytes_to_read -= xfer_len;
+    }
 
-       ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
+    strcat(cons_line, "Done\n");
+    write(STDIO_FD, cons_line, wsz.ws_col);
 
-       num_files++;
-       tmp_file_tag = ezxml_next(tmp_file_tag);
-    }
 
+    fclose(in_file);
 
     return 0;
 }