Browse code

partial unsaved implementation

Dario Rodriguez authored on 13/03/2019 23:31:53
Showing 3 changed files
... ...
@@ -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;