... | ... |
@@ -29,10 +29,10 @@ |
29 | 29 |
#define UNSAVEDPOSTFIX ".reu" |
30 | 30 |
#define SECURESAVEPREFIX "." |
31 | 31 |
#define SECURESAVEPOSTFIX ".saving" |
32 |
-#define UNSAVEDHEADER "REUNSAV\n" |
|
33 |
-#define UNSAVEDVERSION "\n000001\0" |
|
32 |
+#define UNSAVEDHEADER "reunsaved00," |
|
34 | 33 |
|
35 | 34 |
static int redata_hash_gen(redata_t *redata, char *filename, char *buf, long buflen, char *resbuf129bytes); |
35 |
+static int redata_unsaved_check_gen(redata_t *redata, char *filename); |
|
36 | 36 |
static char *unsaved_genname(char *filename, char *buf, int bufsize); |
37 | 37 |
static char *securesave_genname(char *filename, char *buf, int bufsize); |
38 | 38 |
static char *genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize); |
... | ... |
@@ -57,7 +57,6 @@ redata_init(void) |
57 | 57 |
/* unsaved */ |
58 | 58 |
redata->filename[0]='\0'; |
59 | 59 |
redata->unsavedfd=-1; |
60 |
- redata->flag_unsaveddata=0; |
|
61 | 60 |
/* all done */ |
62 | 61 |
return(redata); |
63 | 62 |
} |
... | ... |
@@ -84,13 +83,22 @@ redata_free(redata_t *redata) |
84 | 83 |
free(redata->undostack.undo),redata->undostack.undo=NULL; |
85 | 84 |
if(redata->undostack.buf!=NULL) |
86 | 85 |
free(redata->undostack.buf),redata->undostack.buf=NULL; |
86 |
+ /* redo */ |
|
87 |
+ if(redata->redostack.undo!=NULL) |
|
88 |
+ free(redata->redostack.undo),redata->redostack.undo=NULL; |
|
89 |
+ if(redata->redostack.buf!=NULL) |
|
90 |
+ free(redata->redostack.buf),redata->redostack.buf=NULL; |
|
87 | 91 |
/* unsaved */ |
88 | 92 |
if(redata->unsavedfd!=-1) { |
89 | 93 |
close(redata->unsavedfd),redata->unsavedfd=-1; |
90 | 94 |
if(unsaved_genname(redata->filename,unsname,sizeof(unsname))!=NULL) |
91 | 95 |
unlink(unsname); |
92 | 96 |
} |
93 |
- redata->flag_unsaveddata=0; |
|
97 |
+ if(redata->unsaved.buf!=NULL) { |
|
98 |
+ free(redata->unsaved.buf),redata->unsaved.buf=NULL; |
|
99 |
+ redata->unsaved.sizebuf=redata->unsaved.usedbuf=0; |
|
100 |
+ redata->unsaved.lastsize=0; |
|
101 |
+ } |
|
94 | 102 |
/* free main struct */ |
95 | 103 |
free(redata),redata=NULL; |
96 | 104 |
return; |
... | ... |
@@ -171,8 +179,8 @@ redata_wipe(redata_t *redata) |
171 | 179 |
if(unsaved_genname(redata->filename,unsname,sizeof(unsname))!=NULL) |
172 | 180 |
unlink(unsname); |
173 | 181 |
} |
174 |
- redata->flag_unsaveddata=0; |
|
175 | 182 |
redata->filename[0]='\0'; |
183 |
+ redata->unsaved.usedbuf=0; |
|
176 | 184 |
/* all done */ |
177 | 185 |
return(0); |
178 | 186 |
} |
... | ... |
@@ -427,14 +435,14 @@ redata_unsaved_exists(redata_t *redata, char *filename) |
427 | 435 |
return(0); |
428 | 436 |
} |
429 | 437 |
|
430 |
-int |
|
431 |
-redata_unsaved_check(redata_t *redata, char *filename) |
|
438 |
+static int |
|
439 |
+redata_unsaved_check_gen(redata_t *redata, char *filename) |
|
432 | 440 |
{ |
433 | 441 |
char unsname[PATH_MAX+1]; |
434 | 442 |
int fd,nread; |
435 |
- static char header[9]={UNSAVEDHEADER}; |
|
436 |
- static char version[9]={UNSAVEDVERSION}; |
|
437 |
- char filehash[129],undohash[129],buf[64]; |
|
443 |
+ static char header[]={UNSAVEDHEADER}; |
|
444 |
+ char filehash[129],undohash[129],buf[16]; |
|
445 |
+ char fileheader[]={UNSAVEDHEADER}; |
|
438 | 446 |
if(redata==NULL || filename==NULL) |
439 | 447 |
return(-1); /* sanity check failed */ |
440 | 448 |
if((unsaved_genname(filename,unsname,sizeof(unsname)))==NULL) |
... | ... |
@@ -443,7 +451,9 @@ redata_unsaved_check(redata_t *redata, char *filename) |
443 | 451 |
return(-1); |
444 | 452 |
if((fd=open(unsname,O_RDONLY))==-1) |
445 | 453 |
return(-1); |
446 |
- if((nread=read(fd,buf,8))==-1 || nread!=8 || memcmp(buf,header,8)!=0) { |
|
454 |
+ memset(fileheader,0,sizeof(fileheader)); |
|
455 |
+ if((nread=read(fd,fileheader,sizeof(fileheader)-1))==-1 |
|
456 |
+ || nread!=(sizeof(fileheader)-1) || memcmp(fileheader,header,sizeof(fileheader))!=0) { |
|
447 | 457 |
close(fd),fd=-1; |
448 | 458 |
return(-1); /* corrupted header */ |
449 | 459 |
} |
... | ... |
@@ -451,10 +461,19 @@ redata_unsaved_check(redata_t *redata, char *filename) |
451 | 461 |
close(fd),fd=-1; |
452 | 462 |
return(-1); /* wrong hash */ |
453 | 463 |
} |
454 |
- if((nread=read(fd,buf,8))==-1 || nread!=8 || memcmp(buf,version,8)!=0) { |
|
464 |
+ if((nread=read(fd,buf,1))==-1 || nread!=1 || *buf!=',') { |
|
455 | 465 |
close(fd),fd=-1; |
456 |
- return(-1); /* wrong version */ |
|
466 |
+ return(-1); /* wrong hash separator */ |
|
457 | 467 |
} |
468 |
+ return(fd); |
|
469 |
+} |
|
470 |
+ |
|
471 |
+int |
|
472 |
+redata_unsaved_check(redata_t *redata, char *filename) |
|
473 |
+{ |
|
474 |
+ int fd; |
|
475 |
+ if((fd=redata_unsaved_check(redata,filename))==-1) |
|
476 |
+ return(-1); /* check failed */ |
|
458 | 477 |
close(fd),fd=-1; |
459 | 478 |
return(0); |
460 | 479 |
} |
... | ... |
@@ -474,28 +493,28 @@ redata_unsaved_unlink(redata_t *redata) |
474 | 493 |
return(0); |
475 | 494 |
} |
476 | 495 |
|
477 |
- |
|
478 |
- |
|
479 | 496 |
int |
480 | 497 |
redata_unsaved_trunc(redata_t *redata) |
481 | 498 |
{ |
482 | 499 |
char unsname[PATH_MAX+1]; |
483 |
- static char header[9]={UNSAVEDHEADER}; |
|
484 |
- static char version[9]={UNSAVEDVERSION}; |
|
500 |
+ static char header[]={UNSAVEDHEADER}; |
|
485 | 501 |
int n; |
486 | 502 |
if(redata==NULL || redata->filename[0]=='\0') |
487 | 503 |
return(-1); /* sanity check failed */ |
488 | 504 |
redata_unsaved_unlink(redata); |
489 | 505 |
if((unsaved_genname(redata->filename,unsname,sizeof(unsname)))==NULL) |
490 | 506 |
return(-1); /* malformed filename */ |
507 |
+ if(redata->unsavedfd!=-1) |
|
508 |
+ close(redata->unsavedfd),redata->unsavedfd=-1; |
|
491 | 509 |
if((redata->unsavedfd=open(unsname,O_WRONLY|O_TRUNC|O_CREAT,0644))==-1) |
492 | 510 |
return(-1); /* couldn't open file for writing */ |
493 |
- if((n=write(redata->unsavedfd,header,8))==-1 || n!=8 || |
|
494 |
- (n=write(redata->unsavedfd,redata->initialhash,128))==-1 || n!=128 || |
|
495 |
- (n=write(redata->unsavedfd,version,8))==-1 || n!=8) { |
|
511 |
+ if((n=write(redata->unsavedfd,header,sizeof(header)-1))==-1 |
|
512 |
+ || n!=(sizeof(header)-1) |
|
513 |
+ || (n=write(redata->unsavedfd,redata->initialhash,128))==-1 || n!=128 |
|
514 |
+ || (n=write(redata->unsavedfd,",",1))==-1 || n!=1) { |
|
496 | 515 |
close(redata->unsavedfd),redata->unsavedfd=-1; |
497 | 516 |
unlink(unsname); |
498 |
- return(-1); /* couldn't write header/hash/version */ |
|
517 |
+ return(-1); /* couldn't write header/hash */ |
|
499 | 518 |
} |
500 | 519 |
return(0); |
501 | 520 |
} |
... | ... |
@@ -503,6 +522,40 @@ redata_unsaved_trunc(redata_t *redata) |
503 | 522 |
int |
504 | 523 |
redata_unsaved_loadappend(redata_t *redata) |
505 | 524 |
{ |
525 |
+ int fd; |
|
526 |
+ struct stat statbuf; |
|
527 |
+ static char header[]={UNSAVEDHEADER}; |
|
528 |
+ long headerhashsize; |
|
529 |
+ char *newptr; |
|
530 |
+ long nread,lim; |
|
531 |
+ if((fd=redata_unsaved_check(redata,redata->filename))==-1) |
|
532 |
+ return(-1); /* check failed */ |
|
533 |
+ if(fstat(fd,&statbuf)!=0 || !S_ISREG(statbuf.st_mode)) { |
|
534 |
+ close(fd),fd=-1; |
|
535 |
+ return(-1); /* couldn't query size or not regular file */ |
|
536 |
+ } |
|
537 |
+ headerhashsize=(sizeof(header)-1)+1+128+1; |
|
538 |
+ /* load unsaved to memory */ |
|
539 |
+ if(redata->unsaved.sizebuf<(statbuf.st_size-headerhashsize)) { |
|
540 |
+ if((newptr=realloc(redata->unsaved.buf,(statbuf.st_size-headerhashsize)))==NULL) { |
|
541 |
+ close(fd),fd=-1; |
|
542 |
+ return(-1); /* insuf. mem. */ |
|
543 |
+ } |
|
544 |
+ redata->unsaved.buf=newptr; |
|
545 |
+ redata->unsaved.sizebuf=(statbuf.st_size-headerhashsize); |
|
546 |
+ } |
|
547 |
+ redata->unsaved.lastsize=0; |
|
548 |
+ redata->unsaved.usedbuf=0; |
|
549 |
+ lim=(statbuf.st_size-headerhashsize); |
|
550 |
+ for(nread=0;redata->unsaved.usedbuf<lim;redata->unsaved.usedbuf+=nread,nread=0) { |
|
551 |
+ if((nread=read(fd,redata->unsaved.buf+redata->unsaved.usedbuf,lim-redata->unsaved.usedbuf))<=0) { |
|
552 |
+ redata->unsaved.usedbuf=0; |
|
553 |
+ close(fd),fd=-1; |
|
554 |
+ return(-1); /* short read */ |
|
555 |
+ } |
|
556 |
+ } |
|
557 |
+ close(fd),fd=-1; |
|
558 |
+ /* process unsaved data */ |
|
506 | 559 |
#warning TODO |
507 | 560 |
return(-1); |
508 | 561 |
} |
... | ... |
@@ -511,6 +564,8 @@ redata_unsaved_loadappend(redata_t *redata) |
511 | 564 |
int |
512 | 565 |
redata_unsaved_add(redata_t *redata, undo_t *undo) |
513 | 566 |
{ |
567 |
+ /* separator is '$' , '@' or '%' (whatever makes the longest string) */ |
|
568 |
+ /* if len is omitted, then it goes inmediatly after the last op (probably there separator character was used in the string) */ |
|
514 | 569 |
#warning TODO |
515 | 570 |
return(-1); |
516 | 571 |
} |
... | ... |
@@ -615,8 +670,8 @@ redata_save(redata_t *redata, char *filename) |
615 | 670 |
return(-1); /* couldn't overwrite old file */ |
616 | 671 |
} |
617 | 672 |
redata_unsaved_unlink(redata); |
618 |
- redata->flag_unsaveddata=0; |
|
619 | 673 |
redata_hash(redata,redata->initialhash); |
674 |
+ redata->unsaved.usedbuf=0; |
|
620 | 675 |
return(0); |
621 | 676 |
} |
622 | 677 |
|
... | ... |
@@ -38,11 +38,18 @@ typedef struct undostack_t { |
38 | 38 |
int sizeundo; |
39 | 39 |
int usedundo; |
40 | 40 |
undo_t *undo; |
41 |
- int sizebuf; |
|
42 |
- int usedbuf; |
|
41 |
+ long sizebuf; |
|
42 |
+ long usedbuf; |
|
43 | 43 |
char *buf; |
44 | 44 |
} undostack_t; |
45 | 45 |
|
46 |
+typedef struct unsaved_t { |
|
47 |
+ long sizebuf; |
|
48 |
+ long usedbuf; |
|
49 |
+ char *buf; |
|
50 |
+ long lastsize; |
|
51 |
+} unsaved_t; |
|
52 |
+ |
|
46 | 53 |
typedef struct redata_t { |
47 | 54 |
/* data */ |
48 | 55 |
long chunkdatasize; |
... | ... |
@@ -54,11 +61,10 @@ typedef struct redata_t { |
54 | 61 |
undostack_t undostack; |
55 | 62 |
undostack_t redostack; |
56 | 63 |
/* unsaved (for recovery when the program closes unexpectedly) */ |
57 |
- undostack_t unsavedstack; |
|
58 | 64 |
char filename[PATH_MAX]; |
59 | 65 |
char initialhash[129]; |
60 | 66 |
int unsavedfd; |
61 |
- int flag_unsaveddata; |
|
67 |
+ unsaved_t unsaved; |
|
62 | 68 |
} redata_t; |
63 | 69 |
|
64 | 70 |
redata_t *redata_init(void); |
... | ... |
@@ -47,7 +47,7 @@ main(int argc, char *argv[]) |
47 | 47 |
{"newfile_32768",test_newfile,PREFIX "FILE", NULL, 32768, 0}, |
48 | 48 |
{"newfile_32769",test_newfile,PREFIX "FILE", NULL, 32769, 0}, |
49 | 49 |
{"newfile_131072",test_newfile,PREFIX "FILE", NULL, 131072, 0}, |
50 |
- {"testedit_add",test_edit,PREFIX "EDIT", "A,0,$,Testing add$",0,0}, |
|
50 |
+ {"testedit_add",test_edit,PREFIX "EDIT", "A,0,$Testing add$",0,0}, |
|
51 | 51 |
}; |
52 | 52 |
redata_t *redata; |
53 | 53 |
int i; |
... | ... |
@@ -186,7 +186,6 @@ if(k!=0) redata_save(redata,"test.pre"); |
186 | 186 |
ptr+=(*ptr==',')?1:0; |
187 | 187 |
endcode=*ptr; |
188 | 188 |
ptr+=(*ptr!='\0')?1:0; |
189 |
- ptr+=(*ptr==',')?1:0; |
|
190 | 189 |
ptrend=strchr(ptr,endcode); |
191 | 190 |
ptrend=(ptrend==NULL)?ptr+strlen(ptr):ptrend; |
192 | 191 |
size=ptrend-ptr; |