diff options
-rw-r--r-- | src/cursesview.c | 180 | ||||
-rw-r--r-- | src/ddhardrescue.c | 116 | ||||
-rw-r--r-- | src/recover.c | 20 | ||||
-rw-r--r-- | src/slices.c | 15 | ||||
-rw-r--r-- | src/slices_evt.c | 11 | ||||
-rw-r--r-- | src/utils.c | 78 |
6 files changed, 220 insertions, 200 deletions
diff --git a/src/cursesview.c b/src/cursesview.c new file mode 100644 index 0000000..b032356 --- /dev/null +++ b/src/cursesview.c @@ -0,0 +1,180 @@ +#include "cursesview.h" + +#include <pthread.h> +#include <curses.h> +#include <panel.h> +#include <string.h> + +#define CURSESWIN_COUNT 3 + +// Global variable shared by all threads to say "finish current operation and go away" +extern int end; + +// window updated by cursesUpdateSliceDump callback from "worker" thread, with a mutex for prevent fuzzy concurrent updates +WINDOW *winUpdateSliceDump=NULL; +static pthread_mutex_t ncursesWriteMutex = PTHREAD_MUTEX_INITIALIZER; + +// Helpers declaration (below the interesting code of this file) +int cursesInit(WINDOW *wins[], PANEL *panels[], int count); +void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count); +void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice); +void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); +void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]); + +void cursesMainLoop(slices_evt_t *slicesEvt) { + WINDOW *wins[CURSESWIN_COUNT]; + PANEL *panels[CURSESWIN_COUNT]; + int ch, i; + char str[2]; + + cursesInit(wins, panels, CURSESWIN_COUNT); + + wattron(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4)); + mvwprintw(wins[CURSESWIN_COUNT-1], 1, 0, "(F2 to Exit)"); +// wattroff(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4)); + + update_panels(); + doupdate(); + + /* Enable worker listener */ + //FIXME : check pointers ? + winUpdateSliceDump=wins[1]; + slicesEvt->eventListener=cursesUpdateSliceDump; + + while((ch = getch()) != KEY_F(2)) { + + pthread_mutex_lock(&ncursesWriteMutex); + + switch(ch) { + case '1': + case '2': + case '3': + str[0]=ch; str[1]='\0'; // int (ascii value+flags) to string + i=strtol(str, (char **)NULL, 10); // string to real integer + if (i>0 && i<=CURSESWIN_COUNT) { + top_panel(panels[i-1]); + update_panels(); + } + break; + } + + doupdate(); + + pthread_mutex_unlock(&ncursesWriteMutex); + } + + pthread_mutex_lock(&(slicesEvt->eventListenerMutex)); + slicesEvt->eventListener=NULL; + pthread_mutex_unlock(&(slicesEvt->eventListenerMutex)); + + end=1; + cursesUnInit(wins, panels, CURSESWIN_COUNT); +} + +int cursesInit(WINDOW *wins[], PANEL *panels[], int count) { + int screenH, screenW; + + /* Initialize curses */ + initscr(); + start_color(); + raw(); + keypad(stdscr, TRUE); + noecho(); + + /* Initialize all the colors */ + init_pair(1, COLOR_WHITE, COLOR_BLACK); + init_pair(2, COLOR_WHITE, COLOR_BLUE); + init_pair(3, COLOR_BLUE, COLOR_BLACK); + init_pair(4, COLOR_CYAN, COLOR_BLACK); + + /* Initialize windows and panels */ + getmaxyx(stdscr, screenH, screenW); + if ( screenH < 8 || screenW < 40 ) return 1; + + makeWin(wins+0, panels+0, 3 , screenW, 0 , 0, "Menu"); + makeWin(wins+1, panels+1, screenH-6 , screenW, 3 , 0, "Main Win"); + makeWin(wins+2, panels+2, 2 , screenW, screenH-3 , 0, "Commands"); + + /* Set up the user pointers to the next panel + set_panel_userptr(panels[0], panels[1]); + set_panel_userptr(panels[1], panels[2]); + set_panel_userptr(panels[2], panels[0]); + */ + + /* Update the stacking order. 2nd panel will be on top */ + update_panels(); + + return 0; +} + +void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count) { + int i; + + for (i=0;i<count;i++) { + del_panel(panels[i]); + delwin(wins[i]); + } + endwin(); +} + +void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice) { +// char *strProgress="|/-\\"; +// static int progress=0; + char *toPrint; + address_t blockSize=0; + unsigned int charCount=(getmaxx(winUpdateSliceDump)-getbegx(winUpdateSliceDump))*(getmaxy(winUpdateSliceDump)-getbegy(winUpdateSliceDump)+2); + + //TODO : refesh only right parts of the representation + pthread_mutex_lock(&ncursesWriteMutex); + + toPrint=slicesDump(slicesEvt->data, &blockSize, charCount, slicesEvt->data->min, slicesEvt->data->max); + if (toPrint != NULL) { + attron(COLOR_PAIR(4)); + mvwprintw(winUpdateSliceDump, 1, 0, toPrint); +// attroff(COLOR_PAIR(4)); + + update_panels(); + doupdate(); + + free(toPrint); + } + +/* sprintf(toPrint, "%c - %p %p", strProgress[progress], slicesEvt, modifiedSlice); + progress=(progress+1)%strlen(strProgress); +*/ + pthread_mutex_unlock(&ncursesWriteMutex); +} + + +void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) +{ int length, x, y; + float temp; + + if(win == NULL) + win = stdscr; + getyx(win, y, x); + if(startx != 0) + x = startx; + if(starty != 0) + y = starty; + if(width == 0) + width = 80; + + length = strlen(string); + temp = (width - length)/ 2; + x = startx + (int)temp; + wattron(win, color); + mvwprintw(win, y, x, "%s", string); + wattroff(win, color); + refresh(); +} + +void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]) { + int i; + *win = newwin(h, w, y, x); + mvwprintw(*win, 0, 0, "%s", title); + mvwchgat(*win, 0, 0, -1, A_BOLD, 2, NULL); + for(i=1;i<h;i++) mvwchgat(*win, i, 0, -1, A_STANDOUT, 1, NULL); + *panel = new_panel(*win); +} + diff --git a/src/ddhardrescue.c b/src/ddhardrescue.c index e10d323..67c061b 100644 --- a/src/ddhardrescue.c +++ b/src/ddhardrescue.c @@ -1,39 +1,34 @@ -#include <stdio.h> -#include <stdlib.h> #include <signal.h> -#include <stdint.h> -#include <string.h> #include <pthread.h> +#include <string.h> /* For memset() */ #include "slices_evt.h" -#include "recover.h" #include "utils.h" +#include "recover.h" +#include "cursesview.h" // Global variable shared by all threads to say "finish current operation and go away" int end=0; -WINDOW *winUpdateSliceDump=NULL; -static pthread_mutex_t ncursesWriteMutex = PTHREAD_MUTEX_INITIALIZER; - -struct threadArgs { - struct progArgs *progArgs; - slices_evt_t *slices; -}; - void sigHookAbrt() { end=1; } -// Main procedures of each thread +// Main thread procedures declaration and a struct for passing arguments in a clean way void *procWorker(void *a); void *procViewer(void *a); +struct threadArgs { + struct progArgs *progArgs; + slices_evt_t *slices; +}; + int main(int argc, char **argv) { // System structures struct sigaction sa; pthread_t tWorker; - // Main data structures + // Main data structure slices_evt_t slices; // Progam and threads arguments @@ -42,7 +37,6 @@ int main(int argc, char **argv) { // Algorithmic needs int res, i; - // Parse command-line arguments res=parseArgs(argc, argv, &args); @@ -62,8 +56,8 @@ int main(int argc, char **argv) { //XXX Remove srand : only for simulation srand(4); - // Data structure initialization - // TODO : provides a standard method to do that ? + // Initialize main data structure + //XXX provide a method to do that ? memset(&slices, 0, sizeof(slices)); slices.data=slicesNewSingleton(args.beginSector, args.endSector, S_UNKNOWN); if ( slices.data == NULL ) { @@ -71,7 +65,6 @@ int main(int argc, char **argv) { } slices.data->min=args.beginSector; slices.data->max=args.endSector; - res=pthread_mutex_init(&(slices.eventListenerMutex), NULL); if (res!=0) { return 4; @@ -91,13 +84,13 @@ int main(int argc, char **argv) { // Ncurses interface run in the main thread (void) procViewer((void*)&tArgs); - // Thread join point + // Thread join point (wait worker thread when viewer is done) (void) pthread_join(tWorker, NULL); //Final dump of datas address_t blockSize=0; char *dump; - dump=slicesDump(slices.data, &blockSize, 1000, args.beginSector, args.endSector); + dump=slicesDump(slices.data, &blockSize, 10000, args.beginSector, args.endSector); if (dump != NULL) { puts(dump); free(dump); @@ -109,6 +102,7 @@ int main(int argc, char **argv) { //Resources desallocation (void) pthread_mutex_destroy(&(slices.eventListenerMutex)); + //XXX Method for that slice_t *curr, *toFree; i=0; curr=slices.data->first; while (curr!=NULL) { @@ -125,6 +119,7 @@ int main(int argc, char **argv) { void *procWorker(void *a) { struct threadArgs *tArgs = (struct threadArgs *)a; + //XXX : We will need something more controlable than just a blocking call to the main algorithm recover( tArgs->slices, tArgs->progArgs->src, @@ -135,87 +130,14 @@ void *procWorker(void *a) { return a; } -void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice) { -// char *strProgress="|/-\\"; -// static int progress=0; - char *toPrint; - address_t blockSize=0; - unsigned int charCount=(getmaxx(winUpdateSliceDump)-getbegx(winUpdateSliceDump))*(getmaxy(winUpdateSliceDump)-getbegy(winUpdateSliceDump)+2); - -//FIXME : do that realy - pthread_mutex_lock(&ncursesWriteMutex); - toPrint=slicesDump(slicesEvt->data, &blockSize, charCount, slicesEvt->data->min, slicesEvt->data->max); - if (toPrint != NULL) { - attron(COLOR_PAIR(4)); - mvwprintw(winUpdateSliceDump, 1, 0, toPrint); -// attroff(COLOR_PAIR(4)); - - update_panels(); - doupdate(); - - free(toPrint); - } - -/* sprintf(toPrint, "%c - %p %p", strProgress[progress], slicesEvt, modifiedSlice); - progress=(progress+1)%strlen(strProgress); -*/ - pthread_mutex_unlock(&ncursesWriteMutex); -} - -#define CURSESWIN_COUNT 3 void *procViewer(void *a) { - WINDOW *wins[CURSESWIN_COUNT]; - PANEL *panels[CURSESWIN_COUNT]; - int ch, i; - char str[2]; struct threadArgs *tArgs = (struct threadArgs *)a; - - - cursesInit(wins, panels, CURSESWIN_COUNT); - - wattron(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4)); - mvwprintw(wins[CURSESWIN_COUNT-1], 1, 0, "(F2 to Exit)"); -// wattroff(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4)); - update_panels(); - doupdate(); - - /* Enable worker listener */ - //FIXME : check pointers ? - winUpdateSliceDump=wins[1]; - tArgs->slices->eventListener=cursesUpdateSliceDump; - - while((ch = getch()) != KEY_F(2)) { - - pthread_mutex_lock(&ncursesWriteMutex); - - switch(ch) { - case '1': - case '2': - case '3': - str[0]=ch; str[1]='\0'; // int (ascii value+flags) to string - i=strtol(str, (char **)NULL, 10); // string to real integer - if (i>0 && i<=CURSESWIN_COUNT) { - top_panel(panels[i-1]); - update_panels(); - } - break; - } - - doupdate(); - - pthread_mutex_unlock(&ncursesWriteMutex); - } - - pthread_mutex_lock(&(tArgs->slices->eventListenerMutex)); - tArgs->slices->eventListener=NULL; - pthread_mutex_unlock(&(tArgs->slices->eventListenerMutex)); - - end=1; - cursesUnInit(wins, panels, CURSESWIN_COUNT); + cursesMainLoop( + tArgs->slices + ); return a; } - diff --git a/src/recover.c b/src/recover.c index e6e574a..2131542 100644 --- a/src/recover.c +++ b/src/recover.c @@ -1,10 +1,10 @@ -#include <errno.h> -#include <stdio.h> #include "recover.h" -// Just for sleep -#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> /* for usleep - to be removed */ +// Main algorithm for recover datas void recover(slices_evt_t *slicesEvt, char *src, char *dst, char *ddOpts) { slice_t *sliceToRead; address_t firstError=0, median, foundMax=0; @@ -62,21 +62,24 @@ void recover(slices_evt_t *slicesEvt, char *src, char *dst, char *ddOpts) { break; case 3: // Internal error of sliceSlpit because this set of parameters prevent split by 3 - exit(5); // TODO + exit(6); // TODO break; case -1: // Memory error - exit(4); //TODO + exit(5); //TODO break; default: // API error, all necessary cases are already listed - exit(6); // TODO + exit(7); // TODO } } } +// Method tha read source (and clone to dest) until the first read error int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError, char *src, char *dst, char*ddOpts) { //TODO : implement realy that + //TODO : bail out hardly if WRITE error (on dest) + // char ddinvocation[256]; int res; address_t seek, count; @@ -117,7 +120,8 @@ int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError, char *src, *firstError=error; } - usleep(10000); + // Keep things humanly understandable (to be removed when real reads will be done) + //usleep(10000); return res; } diff --git a/src/slices.c b/src/slices.c index d077454..e84facf 100644 --- a/src/slices.c +++ b/src/slices.c @@ -1,13 +1,10 @@ -#include <string.h> #include "slices.h" -//for perror -#include <stdio.h> - -//FIXME : avoir une méthode destroy pour les slices qui free le mutex +#include <string.h> +#include <stdio.h> /* For perror() */ -inline int min(int a, int b) { return (a<b)?a:b; } -inline int max(int a, int b) { return (a>b)?a:b; } +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) slice_t *sliceNew(address_t begin, address_t end, sliceStatus_t status, slice_t *next) { slice_t *s; @@ -221,8 +218,8 @@ char *slicesDump(slices_t *slices, address_t *blockSize, unsigned int charCount, if ( (curr->begin >= begin && curr->begin <=end) || ( curr->end >= end && curr->end <= end ) ) { // Draw the slice on the right number of characters - sb=max(0, (curr->begin - begin) / *blockSize); - se=min((curr->end - begin) / *blockSize, charCount-1); + sb=MAX(0, (curr->begin - begin) / *blockSize); + se=MIN((curr->end - begin) / *blockSize, charCount-1); // Debug assertion if (sb >= charCount || se >= charCount) { diff --git a/src/slices_evt.c b/src/slices_evt.c index 9174903..4ed07c6 100644 --- a/src/slices_evt.c +++ b/src/slices_evt.c @@ -1,9 +1,9 @@ -//XXX Suprress that when event queue is terminated +#include "slices_evt.h" + #include <stdio.h> #include <pthread.h> -#include "slices_evt.h" - +// Event-aware version of sliceSplit (reusing it, of course) int sliceEvtSplit(slices_evt_t *slicesEvt, slice_t *initialSlice, address_t splitAt, sliceStatus_t statusBefore, sliceStatus_t statusAt, sliceStatus_t statusAfter) { int res; res=sliceSplit(slicesEvt->data, initialSlice, splitAt, statusBefore, statusAt, statusAfter); @@ -27,8 +27,3 @@ int sliceEvtSplit(slices_evt_t *slicesEvt, slice_t *initialSlice, address_t spli return res; } -/* -void sliceEvtPutEvent(slices_evt_t *slicesEvt, slice_t *modifiedSlice) { - printf("sliceEvtPutEvent %p %p\n", slicesEvt, modifiedSlice); -} -*/ diff --git a/src/utils.c b/src/utils.c index 86917ae..7305b22 100644 --- a/src/utils.c +++ b/src/utils.c @@ -25,81 +25,3 @@ void usage(char *progname) { ", progname); } -void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color) -{ int length, x, y; - float temp; - - if(win == NULL) - win = stdscr; - getyx(win, y, x); - if(startx != 0) - x = startx; - if(starty != 0) - y = starty; - if(width == 0) - width = 80; - - length = strlen(string); - temp = (width - length)/ 2; - x = startx + (int)temp; - wattron(win, color); - mvwprintw(win, y, x, "%s", string); - wattroff(win, color); - refresh(); -} - -void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]) { - int i; - *win = newwin(h, w, y, x); - mvwprintw(*win, 0, 0, "%s", title); - mvwchgat(*win, 0, 0, -1, A_BOLD, 2, NULL); - for(i=1;i<h;i++) mvwchgat(*win, i, 0, -1, A_STANDOUT, 1, NULL); - *panel = new_panel(*win); -} - - -int cursesInit(WINDOW *wins[], PANEL *panels[], int count) { - int screenH, screenW; - - /* Initialize curses */ - initscr(); - start_color(); - raw(); - keypad(stdscr, TRUE); - noecho(); - - /* Initialize all the colors */ - init_pair(1, COLOR_WHITE, COLOR_BLACK); - init_pair(2, COLOR_WHITE, COLOR_BLUE); - init_pair(3, COLOR_BLUE, COLOR_BLACK); - init_pair(4, COLOR_CYAN, COLOR_BLACK); - - /* Initialize windows and panels */ - getmaxyx(stdscr, screenH, screenW); - if ( screenH < 8 || screenW < 40 ) return 1; - - makeWin(wins+0, panels+0, 3 , screenW, 0 , 0, "Menu"); - makeWin(wins+1, panels+1, screenH-6 , screenW, 3 , 0, "Main Win"); - makeWin(wins+2, panels+2, 2 , screenW, screenH-3 , 0, "Commands"); - - /* Set up the user pointers to the next panel - set_panel_userptr(panels[0], panels[1]); - set_panel_userptr(panels[1], panels[2]); - set_panel_userptr(panels[2], panels[0]); - */ - - /* Update the stacking order. 2nd panel will be on top */ - update_panels(); - - return 0; -} - -void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count) { - int i; - - for (i=0;i<count;i++) { - del_panel(panels[i]); - delwin(wins[i]); - } - endwin(); -} |