source: tags/initial/ARBDB/ad_load.c

Last change on this file was 2, checked in by oldcode, 23 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.2 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <string.h>
5#include <malloc.h>
6#include <ctype.h>
7#include <sys/stat.h>
8#include <time.h>
9#include <netinet/in.h>
10
11/*#include "arbdb.h"*/
12#include "adlocal.h"
13#include "admap.h"
14
15
16/********************************************************************************************
17                        Versions:
18                ASCII
19
20                V0      - 20.6.95
21                V1      Full save
22                V2      Differential save
23********************************************************************************************/
24
25long 
26gb_read_ascii(const char *path, GBCONTAINER * gbd)
27{
28    char          **pdat, **p2;
29    if (gbd == NULL)
30                return -1;
31    if (path == NULL)
32                return -1;
33    pdat = gb_read_file(path);
34    if (pdat) {
35                GB_search((GBDATA *)gbd,GB_SYSTEM_FOLDER,GB_CREATE_CONTAINER);          /* Switch to Version 3 */
36                p2 = gb_read_rek(pdat + 1, gbd);
37                if (p2)
38                        if (*p2) {
39                                fprintf(stderr, "error in file: %s\n", path);
40                                gb_file_loc_error(p2, "syntax error before in fi");
41                        };
42                free(pdat[0]);
43                free((char *)pdat);
44    };
45    return 0;
46}
47
48char **gb_read_file(const char *path)
49{       /*      ' ' '\t' '\n' werden entfernt und durch '\0' ersetzt
50                "string" wird zu string\0
51                \0 folgt short  bis zur naechsten '\0'
52                Kommentare #  und  comment werden entfernt
53        */
54
55    register char *t,*t2,*pb;
56    char tab[256],tab2[256],x;
57    register long i;
58    char **pdat;
59    FILE *input;
60    char *buffer;
61    long data_size,pdat_cnt = 0,pdat_size;
62
63    for (i=0;i<256;i++)  { tab[i] = 1;tab2[i]=0;}
64    tab[' '] = 0;
65    tab['\t'] = 0;
66    tab['\n'] = 0;
67    tab['\0'] = 0;
68
69    tab2[' '] = 1;
70    tab2['\t'] = 1;
71    tab2['\n'] = 1;
72    t = tab;t2=tab2;
73    pdat = NULL;data_size = 0;
74    if ((input = fopen(path, "r")) == NULL) {
75                printf(" file %s not found\n", path);
76    }else{
77                if (fseek(input,0,2)==-1){
78                        printf("file %s not seekable\n",path);
79                }else{
80                        data_size = (long)ftell(input) + 1;
81                        rewind(input);
82                        buffer =  (char *)malloc((size_t)data_size+1);
83                        data_size = fread(buffer,1,(int)data_size,input);
84                        fclose(input);
85                        pdat_size = data_size/CROSS_BUFFER_DIFF+2;
86                        buffer[data_size] = 0;
87                        pdat_cnt = 0;
88                        pdat = (char **)malloc((size_t)(sizeof(char *) * pdat_size));
89                        pdat[pdat_cnt++] = buffer;
90                        pb = buffer;
91                        while ( 1 ) {
92                                if (pdat_cnt == pdat_size){
93                                        pdat_size += data_size/CROSS_BUFFER_DIFF+2;
94                                        pdat = (char **)realloc((char *)pdat,
95                                                                                        (size_t)(sizeof(char *) * pdat_size));
96                                }
97                                while ( t2[(int)(x = *pb)] ) pb++;
98                                if (! x) break;
99                                if (x == '"'){  /* string anfang */
100                                        char *dest;
101                                        if (pb[1] == 1) {       /* old string mode */
102                                                pb += 2;
103                                                pdat[pdat_cnt++] = pb;
104                                                while ( (x = *pb++) ) {
105                                                        if( (x==(char)1) &&
106                                                                (pb[0]==(char)34) )break;
107                                                }
108                                                if (!x) break;
109                                                pb[-1] = 0;
110                                                pb++;
111                                                continue;
112                                        }
113                                        pdat[pdat_cnt++] = ++pb;
114                                        dest = pb;
115                                        while ((x = *pb++) != '"' ){
116                                                if (x == '\\'){
117                                                        x = *pb++;
118                                                        if (!x) break;
119                                                        if (x>='@' && x <='@'+ 25) {
120                                                                *dest++ = x-'@';continue;
121                                                        }
122                                                        if (x>='0' && x <='9') {
123                                                                *dest++ = x-('0'-25);continue;
124                                                        }
125                                                }
126                                                *dest++ = x;
127                                        }
128                                        dest[0] = 0;
129                                        continue;
130                                }
131                                if ( (x == '/') && (pb[1] == '*') ) {   
132                                        while ( (x = *pb++) && ((x != '*') || (*pb !='/')));
133                                        if (!x) break;
134                                        *pb++ = 0;
135                                        continue;
136                                }
137                                if (x == '#') {
138                                        while ( (x= *pb++) && (x != '\n') );    /*ende*/
139                                        if (!x) break;
140                                        continue;
141                                }       
142                                pdat[pdat_cnt++] = pb;
143                                while ( t[(int)(*pb++)] );
144                                pb[-1] = 0;
145                        }
146                }
147                pdat[pdat_cnt] = NULL;
148
149
150                /* all data read */
151               
152    }
153    return pdat;       
154}
155
156/********************************************************************************************
157                        print part of ascii file on error
158********************************************************************************************/
159
160void gb_file_loc_error(char **pdat,const char *s) 
161{
162    long i;
163    printf("error in data_base: %s\n",s);
164    printf("\t the error is followed by:\n");
165    for(i=0; (i<10) && (pdat[i]);i++ ) {
166                printf ("\t\t'%s'\n",pdat[i]);
167    }
168}
169
170/********************************************************************************************
171                                        Read Ascii File
172********************************************************************************************/
173
174char **gb_read_rek(char **pdat,GBCONTAINER *gbd)
175{
176    char *p;
177    char *key;
178    int secr, secw, secd, lu;
179    long        i;
180    GBDATA *previous;
181    GBCONTAINER *gbc;
182    GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gbd);
183
184    previous = NULL;
185    while ( (p = *pdat++) && (*p != '%') ) {
186                key = p;
187                if ( !(p = *pdat++)) break;     /* eof */
188                if (*p==':' && p[-1]!='"' ) {
189                        secd = p[1];A_TO_I(secd);
190                        secw = p[2];A_TO_I(secw);
191                        secr = p[3];A_TO_I(secr);
192                        lu = atoi(p+4);
193                        for (i=Main->last_updated;i<=lu;i++) 
194                        {
195                                Main->dates[i] = GB_STRDUP("unknown date");
196                                Main->last_updated = lu+1;
197                        };
198                        if ( !(p = *pdat++)) break;     /* eof */
199                }else{
200                        secr = secw = secd = 0;
201                        lu = 0;
202                }
203
204                if (*p != '%' || p[-1]=='"' ) 
205                {
206                        previous = gb_make_entry(gbd, key,-1,0,GB_STRING);
207                        GB_write_string(previous,p);
208                        previous->flags.security_delete = secd;
209                        previous->flags.security_write = secw;
210                        previous->flags.security_read = secr;
211                        previous->flags2.last_updated = lu;
212                }else{
213                        if (p[2]) {
214                                gb_file_loc_error(pdat-2,
215                                                                  "illegal option");
216                                return NULL;
217                        }
218                        if (! *pdat) {  gb_file_loc_error(pdat-2,
219                                                                                          "unexpected end of file, long expected");
220                        return NULL;
221                        };/* eof */
222
223
224                        switch (p[1]) {
225                                case 's':
226                                        previous = gb_make_entry(gbd, key, -1,0,GB_STRING);
227                                        GB_write_string(previous,*pdat++);
228                                        break;
229                                case 'l':
230                                        previous = gb_make_entry(gbd, key, -1,0,GB_LINK);
231                                        GB_write_link(previous,*pdat++);
232                                        break;
233                                case 'i':
234                                        previous = gb_make_entry(gbd, key, -1,0,GB_INT);
235                                        p = *pdat++;
236                                        GB_write_int(previous,atoi(p));
237                                        break;
238                                case 'y':
239                                        previous = gb_make_entry(gbd, key, -1,0,GB_BYTE);
240                                        p = *pdat++;
241                                        GB_write_byte(previous,atoi(p));
242                                        break;
243                                case 'f':
244                                        previous = gb_make_entry(gbd, key, -1,0,GB_FLOAT);
245                                        p = *pdat++;
246                                        GB_write_float(previous,GB_atof(p));
247                                        break;
248                                case 'I':
249                                        previous = gb_make_entry(gbd, key, -1,0,GB_BITS);
250                                        p = *(pdat++);
251                                        GB_write_bits(previous,p,strlen(p),'-');
252                                        break;
253                                case 'Y':
254                                        previous = gb_make_entry(gbd, key, -1,0,GB_BYTES);
255                                        if ( gb_ascii_2_bin(*(pdat++),previous)){
256                                                gb_file_loc_error(pdat-2,"error in bytes");
257                                                return 0;
258                                        }
259                                        break;
260                                case 'N':
261                                        previous = gb_make_entry(gbd, key, -1,0,GB_INTS);
262                                        if ( gb_ascii_2_bin(*(pdat++),previous)){
263                                                gb_file_loc_error(pdat-2,"error in ints");
264                                                return 0;
265                                        }
266                                        break;
267                                case 'F':
268                                        previous = gb_make_entry(gbd, key, -1,0,GB_FLOATS);
269                                        if ( gb_ascii_2_bin(*(pdat++),previous)){
270                                                gb_file_loc_error(pdat-2,"error in floats");
271                                                return 0;
272                                        }
273                                        break;
274                                case '%':
275                                        p = *pdat;
276                                        gbc = gb_make_container(gbd, key, -1,0);
277                                        previous = (GBDATA *)gbc;
278                                        if (*p != '(') {
279                                                pdat ++;
280                                                p = *pdat;
281                                        }
282                                        if ( (*p =='(')&&(p[1]=='%')){
283                                                if (!(pdat = gb_read_rek(pdat+1,gbc))){
284                                                        return NULL;
285                                                }
286                                                if ( (!(p=*pdat)) || (*p !='%')||(p[1]!=')')){
287                                                        gb_file_loc_error(pdat-2,
288                                                                                          "unexpected end of file, %%) expected");
289                                                        return NULL;
290                                                }
291                                                pdat++;
292                                        }else{
293                                                gb_file_loc_error(pdat-2,
294                                                                                  "no '(' found, %");
295                                                return NULL;
296                                        }
297                                        break;
298                                default:        gb_file_loc_error(pdat-2,
299                                                                                          "unknown option");
300                                        return NULL;
301                        } /*switch */
302                        previous->flags.security_delete = secd;
303                        previous->flags.security_write = secw;
304                        previous->flags.security_read = secr;
305                        previous->flags2.last_updated = lu;
306                } /* if */
307    } /* while */
308    return pdat-1;
309}
310
311long gb_read_bin_rek(FILE *in,GBCONTAINER *gbd,long nitems,long version,long reversed)
312{
313    long item;
314    long type,type2;
315    GBQUARK key;
316    register char *p;
317    register long i;
318    register int c;
319    long size;
320    long memsize;
321    GBDATA *gb2;
322    GBCONTAINER *gbc =0 ;
323    long security;
324    char *buff;
325    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
326
327    gb_create_header_array(gbd,(int)nitems);
328
329    for (item = 0;item<nitems;item++) {
330                type = getc(in);
331                security = getc(in);
332                type2 = (type>>4)&0xf;
333                key = getc(in);
334                if (!key){
335                        p = gb_local->buffer;
336                        for (i=0;i<256;i++) {
337                                c = getc(in);
338                                *(p++) = c;
339                                if (!c) break;
340                                if (c==EOF) {
341                                        gb_read_bin_error(in,(GBDATA *)gbd,"Unexpected EOF found");
342                                        return -1;
343                                }
344                        }
345                        if (i>GB_KEY_LEN_MAX*2) {
346                                gb_read_bin_error(in,(GBDATA *)gbd,"Key to long");
347                                return -1;
348                        }
349                        if (type2 == (long)GB_DB){
350                                gbc = gb_make_container(gbd,gb_local->buffer,-1,0);
351                                gb2 = (GBDATA *)gbc;
352                        }else{
353                                gb2 = gb_make_entry(gbd,gb_local->buffer,-1,0,(GB_TYPES)type2);
354                        }
355                }else{
356                        if (type2 == (long)GB_DB){
357                                gbc = gb_make_container(gbd,NULL,-1,key);
358                                gb2 = (GBDATA *)gbc;
359                        }else{
360                                gb2 = gb_make_entry(gbd,NULL,-1,(GBQUARK)key,(GB_TYPES)type2);
361                        }
362                        if (!Main->keys[key].key) {
363                                GB_internal_error("Some database fields have no field indentifier -> setting to 'main'");
364                                gb_write_index_key(GB_FATHER(gbd),gbd->index,0);
365                        }
366                }
367                gb2->flags.security_delete      = type >> 1;
368                gb2->flags.security_write       = ((type&1) << 2 ) + (security >>6);
369                gb2->flags.security_read        = security >> 3;
370                gb2->flags.compressed_data      = security >> 2;
371                GB_ARRAY_FLAGS(((GBCONTAINER*)gb2)).flags = (int)((security >> 1) & 1);
372                gb2->flags.unused               = security >> 0;
373                gb2->flags2.last_updated = getc(in);
374
375                switch (type2) {
376                        case GB_INT:
377                                {
378                                        GB_UINT4 buffer;
379                                        if (!fread((char*)&buffer,sizeof(GB_UINT4),1,in) ) {
380                                                GB_export_error("File too short, seems truncated");
381                                                return -1;
382                                        }
383                                        gb2->info.i = ntohl(buffer);
384                                        break;
385                                }
386                        case GB_FLOAT:
387                                gb2->info.i = 0;
388                                if (!fread((char*)&gb2->info.i,sizeof(float),1,in) ) {
389                                        return -1;
390                                }
391                                break;
392                        case GB_STRING_SHRT:
393                                p = buff = GB_give_buffer(GBTUM_SHORT_STRING_SIZE+2);
394                                for (size=0;size<=GBTUM_SHORT_STRING_SIZE;size++) {
395                                        if (!(*(p++) = getc(in) )) break;
396                                }
397                                *p=0;
398                                GB_SETSMDMALLOC(gb2,size,size+1,buff);
399                                break;
400                        case GB_STRING:
401                        case GB_LINK:
402                        case GB_BITS:
403                        case GB_BYTES:
404                        case GB_INTS:
405                        case GB_FLOATS:
406                                size = gb_read_in_long(in, reversed);
407                                memsize =  gb_read_in_long(in, reversed);
408                                if (GB_CHECKINTERN(size,memsize) ){
409                                        GB_SETINTERN(gb2);
410                                        p = &(gb2->info.istr.data[0]);
411                                }else{
412                                        GB_SETEXTERN(gb2);
413                                        p = GB_give_buffer(memsize);
414                                }
415                                i = fread(p,1,(size_t)memsize,in);
416                                if (i!=memsize) {
417                                        gb_read_bin_error(in,gb2,"Unexpected EOF found");
418                                        return -1;
419                                }
420                                GB_SETSMDMALLOC(gb2,size,memsize,p);
421                                break;
422                        case GB_DB:
423                                size = gb_read_in_long(in, reversed);
424                                /* gbc->d.size  is automatically incremented */
425                                memsize = gb_read_in_long(in, reversed);
426                                if (gb_read_bin_rek(in,gbc,size,version,reversed)) return -1;
427                                break;
428                        case GB_BYTE:
429                                gb2->info.i = getc(in);
430                                break;
431                        default:
432                                gb_read_bin_error(in,gb2,"Unknown type");
433                                return -1;
434                }
435    }
436    return 0;
437}
438
439
440long gb_recover_corrupt_file(GBCONTAINER *gbd,FILE *in){
441    /* search pattern dx xx xx xx string 0 */
442    static FILE *old_in = 0;
443    static unsigned char *file = 0;
444    static long size = 0;
445    long pos = ftell(in);
446    if (!GBCONTAINER_MAIN(gbd)->allow_corrupt_file_recovery) {
447                GB_export_error("Your data file is corrupt.\n"
448                                                "       This may happen if \n"
449                                                "       - there is a hard drive crash,\n"
450                                                "       - data is corrupted by bad internet connections,\n"
451                                                "       - or the data is destroyed by the program\n"
452                                                "       - it is not an arb file\n"
453                                                "       You may recover part of your data by running\n"
454                                                "               arb_2_ascii old_arb_file panic.arb\n"
455                                                "       or send it to strunk@mikro.biologie.tu-muenchen.de\n");
456                return -1;
457    }
458    pos = ftell(in);
459    if (old_in != in) {
460                file = (unsigned char *)GB_map_FILE(in,0);
461                old_in = in;
462                size = GB_size_of_FILE(in);
463    }
464    for (;pos<size-10;pos ++){
465                if ( ( file[pos] & 0xf0) == (GB_STRING_SHRT<<4)) {
466                        long s;
467                        int c;
468                        for ( s= pos +4; s<size && file[s]; s++ ){
469                                c = file[s];
470                                if (! (isalnum(c) || isspace(c) || strchr("._;:,",c) ) ) break;
471                        }
472                        if ( s< size && s > pos+11 && !file[s]) {       /* we found something */
473                                gb_local->search_system_folder = 1;
474                                return fseek(in,pos,0);
475                        }
476                }
477    }
478    return -1;                  /* no short string found */
479}
480
481
482
483long gb_read_bin_rek_V2(FILE *in,GBCONTAINER *gbd,long nitems,long version,long reversed,long deep)
484{
485    long item;
486    long type,type2;
487    GBQUARK key;
488    register char *p;
489    register long i;
490    long size;
491    long memsize;
492    int index;
493    GBDATA *gb2;
494    GBCONTAINER *gbc;
495    long security;
496    char *buff;
497    GB_MAIN_TYPE *Main = GB_MAIN(gbd);
498    struct gb_header_list_struct *header;
499
500    gb_create_header_array(gbd,(int)nitems);
501    header = GB_DATA_LIST_HEADER(gbd->d);
502    if (deep == 0 && GBCONTAINER_MAIN(gbd)->allow_corrupt_file_recovery) {
503                GB_warning("Read to end of file in recovery mode");
504                nitems = 10000000; /* read forever at highest level */
505    }
506       
507    for (item = 0;item<nitems;item++) 
508    {           
509                type = getc(in);
510                if (type == EOF){
511                        GB_export_error("Unexpected end of file seen");
512                        return -1;
513                }
514                if (!type) {
515                        int func;
516                        if (version == 1) {     /* master file */
517                                if (gb_recover_corrupt_file(gbd,in)) return -1;
518                                continue;
519                        }
520                        func = getc(in);
521                        switch (func) {
522                                case 1:         /*      delete entry    */
523                                        index = (int)gb_read_number(in);
524                                        if (index >= gbd->d.nheader ){
525                                                gb_create_header_array(gbd,index+1);
526                                                header = GB_DATA_LIST_HEADER(gbd->d);
527                                        }
528                                        if ((gb2 = GB_HEADER_LIST_GBD(header[index]))!=NULL) {
529                                                gb_delete_entry(gb2);
530                                                gb2 = NULL;
531                                        }else{
532                                                header[index].flags.ever_changed = 1;
533                                                header[index].flags.changed = gb_deleted;
534                                        }
535
536                                        break;
537                                default:
538                                        if (gb_recover_corrupt_file(gbd,in)) return -1;
539                                        continue;
540                        }
541                        continue;
542                }
543
544                security = getc(in);
545                type2 = (type>>4)&0xf;
546                key = (GBQUARK)gb_read_number(in);
547
548                if (key >= Main->keycnt || !Main->keys[key].key ){
549                        GB_export_error("Inconsistent Database: Changing field identifier to 'main'");
550                        key = 0;
551                }
552
553                gb2 = NULL;
554                gbc = NULL;
555                if (version == 2) {
556                        index = (int)gb_read_number(in);
557                        if (index >= gbd->d.nheader ) {
558                                gb_create_header_array(gbd,index+1);
559                                header = GB_DATA_LIST_HEADER(gbd->d);
560                        }
561               
562                        if (index >= 0 && (gb2 = GB_HEADER_LIST_GBD(header[index]))!=NULL) {
563                                if (    (GB_TYPE(gb2) == GB_DB ) !=
564                                                ( type2 == GB_DB) ) {
565                                        GB_internal_error("Type changed, you may loose data");
566                                        gb_delete_entry(gb2);
567                                        SET_GB_HEADER_LIST_GBD(header[index],NULL);
568                                        gb2 = 0;        /* @@@ OLI */
569                                }else{
570                                        if (type2 == GB_DB){
571                                                gbc = (GBCONTAINER *)gb2;
572                                        }else{
573                                                GB_FREEDATA(gb2);
574                                        }
575                                }                               
576                        }
577                }else{
578                        index = -1;
579                }
580
581
582                if (!gb2) {
583                        if (type2 == (long)GB_DB){
584                                gbc = gb_make_container(gbd,NULL,index, key);
585                                gb2 = (GBDATA *)gbc;
586                        }else{
587                                gb2 = gb_make_entry(gbd,NULL,index, key, (GB_TYPES)type2);
588                                GB_INDEX_CHECK_OUT(gb2);
589                        }
590                }
591
592                if (version == 2) {
593                        GB_CREATE_EXT(gb2);
594                        gb2->ext->update_date = gb2->ext->creation_date = Main->clock;
595                        header[gb2->index].flags.ever_changed = 1;
596                }else{
597                        Main->keys[key].nref_last_saved++;
598                }
599
600                gb2->flags.security_delete      = type >> 1;
601                gb2->flags.security_write       = ((type&1) << 2 ) + (security >>6);
602                gb2->flags.security_read        = security >> 3;
603                gb2->flags.compressed_data      = security >> 2;
604                header[gb2->index].flags.flags  = (int)((security >> 1) & 1);
605                gb2->flags.unused               = security >> 0;
606                gb2->flags2.last_updated = getc(in);
607
608                switch (type2) {
609                        case GB_INT:
610                                {
611                                        GB_UINT4 buffer;
612                                        if (!fread((char*)&buffer,sizeof(GB_UINT4),1,in) ) {
613                                                GB_export_error("File too short, seems truncated");
614                                                return -1;
615                                        }
616                                        gb2->info.i = ntohl(buffer);
617                                        break;
618                                }
619
620                        case GB_FLOAT:
621                                if (!fread((char*)&gb2->info.i,sizeof(float),1,in) ) {
622                                        GB_export_error("File too short, seems truncated");
623                                        return -1;
624                                }
625                                break;
626                        case GB_STRING_SHRT:
627                                i = GB_give_buffer_size();
628                                p = buff = GB_give_buffer(GBTUM_SHORT_STRING_SIZE+2);
629                                size = 0;
630                                while(1){
631                                        for (;size<i;size++) {
632                                                if (!(*(p++) = getc(in) )) goto shrtstring_fully_loaded;
633                                        }
634                                        i = i*3/2;
635                                        buff = gb_increase_buffer(i);
636                                        p = buff + size;
637                                }
638                shrtstring_fully_loaded:
639                                GB_SETSMDMALLOC(gb2,size,size+1,buff);
640                                break;
641                        case GB_STRING:
642                        case GB_LINK:
643                        case GB_BITS:
644                        case GB_BYTES:
645                        case GB_INTS:
646                        case GB_FLOATS:
647                                size = gb_read_number(in);
648                                memsize =  gb_read_number(in);
649                                if (GB_CHECKINTERN(size,memsize) ){
650                                        GB_SETINTERN(gb2);
651                                        p = &(gb2->info.istr.data[0]);
652                                }else{
653                                        GB_SETEXTERN(gb2);
654                                        p = gbm_get_mem((size_t)memsize,GB_GBM_INDEX(gb2));
655                                }
656                                i = fread(p,1,(size_t)memsize,in);
657                                if (i!=memsize) {
658                                        gb_read_bin_error(in,gb2,"Unexpected EOF found");
659                                        return -1;
660                                }
661                                GB_SETSMD(gb2,size,memsize,p);
662                                break;
663                        case GB_DB:
664                                size = gb_read_number(in);
665                                /* gbc->d.size  is automatically incremented */
666                                if (gb_read_bin_rek_V2(in,gbc,size,version,reversed,deep+1)){
667                                        if (!GBCONTAINER_MAIN(gbd)->allow_corrupt_file_recovery) {
668                                                return -1;
669                                        }
670                                }
671                                break;
672                        case GB_BYTE:
673                                gb2->info.i = getc(in);
674                                break;
675                        default:
676                                gb_read_bin_error(in,gb2,"Unknown type");
677                                if (gb_recover_corrupt_file(gbd,in)){
678                                        if (GBCONTAINER_MAIN(gbd)->allow_corrupt_file_recovery){
679                                                return 0;               /* loading stopped */
680                                        }else{
681                                                return -1;
682                                        }
683                                }
684
685                                continue;
686                }
687    }
688    return 0;
689}
690
691GBDATA *gb_search_system_folder_rek(GBDATA *gbd){
692
693
694    GBDATA *gb2;
695    GBDATA *gb_result = 0;
696    for (gb2 = GB_find(gbd,0,0,down_level);
697                 gb2;
698                 gb2 = GB_find(gb2,0,0,this_level|search_next)){
699                int type = GB_read_type(gb2);
700                if (type != GB_DB) continue;
701                if (!strcmp(GB_SYSTEM_FOLDER, GB_read_key_pntr(gb2))){
702                        gb_result = gb2;
703                        break;
704                }
705    }
706    return gb_result;
707}
708
709
710void gb_search_system_folder(GBDATA *gb_main){
711        /* Search a system folder within the database tree
712         *  and copy it to main level */
713    GBDATA *gb_oldsystem;
714    GB_ERROR error;
715    GBDATA *gb_system = GB_find(gb_main,GB_SYSTEM_FOLDER,0,down_level);
716    if (gb_system) return;
717   
718    GB_warning("Searching system information");
719    gb_oldsystem = gb_search_system_folder_rek(gb_main);
720    if (!gb_oldsystem){
721                GB_warning("!!!!! not found (bad)");
722                return;
723    }
724    gb_system = GB_search(gb_main,GB_SYSTEM_FOLDER,GB_CREATE_CONTAINER);
725    error = GB_copy(gb_system,gb_oldsystem);
726    if (!error) error = GB_delete(gb_oldsystem);
727    if (error) GB_warning(error);
728    GB_warning("***** found (good)");
729}
730
731long gb_read_bin(FILE *in,GBCONTAINER *gbd, int diff_file_allowed)
732{
733    register int c = 1;
734    long i;
735    long        error;
736    long        j,k;
737    long        version;
738    long        reversed;
739    long        nodecnt;
740    long        first_free_key;
741    char        *buffer,*p;
742    GB_MAIN_TYPE *Main = GBCONTAINER_MAIN(gbd);
743
744    while ( c && c!= EOF ) {
745                c = getc(in);
746    }
747    if (c==EOF){
748                gb_read_bin_error(in,(GBDATA *)gbd,"First zero not found");
749                return 1;
750    }
751
752    i = gb_read_in_long(in,0);
753    if ( strncmp((char *)&i,"vers",4) ) {
754                gb_read_bin_error(in,(GBDATA *)gbd,"keyword 'vers' not found");
755                return 1;
756    }
757    i = gb_read_in_long(in,0);
758    switch (i) {
759                case 0x01020304:
760                        reversed = 0;
761                        break;
762                case 0x04030201:
763                        reversed = 1;
764                        break;
765                default:
766                        gb_read_bin_error(in,(GBDATA *)gbd,"keyword '^A^B^C^D' not found");
767                        return 1;
768    }
769    version = gb_read_in_long(in,reversed);
770    if (version >2 ) {
771                gb_read_bin_error(in,(GBDATA *)gbd,"ARB Database version > '2'");
772                return 1;
773    }
774
775    if (version == 2 && !diff_file_allowed) {
776                GB_export_error("This is not a primary arb file, please select the master"
777                                                " file xxx.arb");
778                return 1;
779    }
780
781    buffer = GB_give_buffer(256);
782    i = gb_read_in_long(in,0);
783    if ( strncmp((char *)&i,"keys",4) ) {
784                gb_read_bin_error(in,(GBDATA *)gbd,"keyword 'keys' not found");
785                return 1;
786    }
787
788    if (!Main->key_2_index_hash) Main->key_2_index_hash = GBS_create_hash(30000,0);
789       
790    first_free_key = 0;
791    gb_free_all_keys(Main);
792
793    while(1) {                  /* read keys */
794                long nrefs = 0;
795                if (version) {
796                        nrefs = gb_read_number(in);
797                }
798                p = buffer;
799                for (k=0;k<GB_KEY_LEN_MAX;k++) {
800                        c = getc(in);
801                        if (!c) break;
802                        if (c==EOF) {
803                                gb_read_bin_error(in,(GBDATA *)gbd,"unexpected EOF while reading keys");
804                                return 1;
805                        }
806                        *(p++) = c;
807                }
808                *p=0;
809                if (p == buffer) break;
810                if (*buffer == 1) {             /* empty key */
811                        long index = gb_create_key(Main,0,GB_FALSE);
812                        Main->keys[index].key = 0;
813                        Main->keys[index].nref = 0;
814                        Main->keys[index].next_free_key = first_free_key;
815                        first_free_key = index;
816                }else{
817                        long index = gb_create_key(Main,buffer,GB_FALSE);
818                        Main->keys[index].nref = nrefs;
819                }
820
821    }
822    Main->first_free_key = first_free_key;
823
824    i = gb_read_in_long(in,0);
825    if ( strncmp((char *)&i,"time",4) ) {
826                gb_read_bin_error(in,(GBDATA *)gbd,"keyword 'time' not found");
827                return 1;
828    }
829    for (j=0;j<255;j++) {                       /* read times */
830                p = buffer;
831                for (k=0;k<256;k++) {
832                        c = getc(in);
833                        if (!c) break;
834                        if (c==EOF) {
835                                gb_read_bin_error(in,(GBDATA *)gbd,"unexpected EOF while reading times");
836                                return 1;
837                        }
838                        *(p++) = c;
839                }
840                *p=0;
841                if (p == buffer) break;
842                if (Main->dates[j]) free(Main->dates[j]);
843                Main->dates[j] = GB_STRDUP(buffer);
844    }
845    if (j>=255) {
846                gb_read_bin_error(in,(GBDATA *)gbd,"more then 255 dates are not allowed");
847                return 1;
848    }
849    Main->last_updated = (unsigned int)j;
850
851    i = gb_read_in_long(in,0);
852    if ( strncmp((char *)&i,"data",4) ) {
853                gb_read_bin_error(in,(GBDATA *)gbd,"keyword 'data' not found");
854                return 0;
855    }
856    nodecnt = gb_read_in_long(in,reversed);
857    GB_give_buffer(256);
858
859    if (version==1)                     /* teste auf map file falls version == 1 */
860    {
861                GB_CSTR map_path;
862                int     merror;
863                struct gb_map_header mheader;
864                long    mode;
865                int ok=0;
866                mode = GB_mode_of_link(Main->path);     /* old master */
867                if (S_ISLNK(mode)){
868                        char *path2 = GB_follow_unix_link(Main->path);     
869                        map_path = gb_mapfile_name(path2);
870                        free(path2);
871                }else{
872                        map_path = gb_mapfile_name(Main->path);
873                }
874                merror = gb_is_valid_mapfile(map_path,&mheader);
875                if (merror>0)
876                {
877                        if (gb_main_array[mheader.main_idx]==NULL)
878                        {
879                                GBCONTAINER *newGbd = (GBCONTAINER*)gb_map_mapfile(map_path);
880
881                                if (newGbd)
882                                {
883                                        GBCONTAINER     *father = GB_FATHER(gbd);
884                                        GB_MAIN_IDX     new_idx = mheader.main_idx,
885                                                old_idx = father->main_idx;
886
887                                        GB_commit_transaction((GBDATA*)gbd);
888
889                                        ad_assert(newGbd->main_idx == new_idx);
890
891                                        gb_main_array[new_idx] = Main;
892                                        Main->data = newGbd;
893                                        father->main_idx = new_idx;
894
895                                        gbd = newGbd;
896                                        SET_GB_FATHER(gbd,father);
897
898                                        gb_main_array[old_idx]    = NULL;
899
900                                        GB_begin_transaction((GBDATA*)gbd);
901                                        ok=1;   
902                                }
903                        }
904                        else
905                        {
906                                GB_export_error("FastLoad-File index conflict -- please save one\n"
907                                                                "of the loaded databases as\n"
908                                                                "'Bin (with FastLoad File)' again");
909                        }
910                }else{
911                        if (!merror){
912                                GB_warning("%s",GB_get_error());
913                        }else{
914                                printf("        no FastLoad File '%s' found: loading entire database\n",map_path);
915                        }
916                }
917                if (ok) return 0;
918    }
919
920    switch(version) {
921                case 0:
922                        error = gb_read_bin_rek(in,gbd,nodecnt,version,reversed);
923                        break;
924                case 2:
925                        for (i=1; i < Main->keycnt;i++) {
926                                if (Main->keys[i].key) {
927                                        Main->keys[i].nref_last_saved = Main->keys[i].nref;
928                                }
929                        }
930
931                        if (Main->clock<=0) Main->clock++;
932                case 1:
933                        error = gb_read_bin_rek_V2(in,gbd,nodecnt,version,reversed,0);
934                        break;
935                default:
936                        GB_internal_error("Sorry: This ARB Version does not support database format V%i",version);
937                        error = 1;
938    }
939       
940    if (gb_local->search_system_folder){
941                gb_search_system_folder((GBDATA *)gbd);
942    }
943       
944    switch(version) {
945                case 2:
946                case 1:
947                        for (i=1; i < Main->keycnt;i++) {
948                                if (Main->keys[i].key) {
949                                        Main->keys[i].nref = Main->keys[i].nref_last_saved;
950                                }
951                        }
952                        break;
953                default:
954                        break;
955    }
956
957    return error;
958}
959
960/********************************************************************************************
961                                        OPEN DATABASE
962********************************************************************************************/
963
964long    gb_next_main_idx_for_mapfile;
965
966void GB_set_next_main_idx(long idx){
967    gb_next_main_idx_for_mapfile = idx;
968}
969
970GB_MAIN_IDX gb_make_main_idx(GB_MAIN_TYPE *Main)
971{
972    static int initialized = 0;
973    GB_MAIN_IDX idx;
974
975    if (!initialized)
976    {
977                for (idx=0; idx<GB_MAIN_ARRAY_SIZE; idx++)
978                        gb_main_array[idx] = NULL;
979                initialized = 1;
980    }
981    if (gb_next_main_idx_for_mapfile<=0){
982                while (1)       /* search for unused array index */
983                {
984                        idx = (short)(time(NULL) % GB_MAIN_ARRAY_SIZE);
985                        if (gb_main_array[idx]==NULL)
986                                break;
987                }
988    }else{
989                idx = (short)gb_next_main_idx_for_mapfile;
990                gb_next_main_idx_for_mapfile = 0;
991    }
992
993    gb_main_array[idx] = Main;
994
995    return idx; 
996}
997
998GB_ERROR        gb_login_remote(struct gb_main_type *gb_main,const char *path,const char *opent){
999    GBCONTAINER *gbd = gb_main->data;
1000    gb_main->local_mode = GB_FALSE;
1001    gb_main->c_link = gbcmc_open(path);
1002
1003    if (!gb_main->c_link) {
1004                return GB_export_error("There is no ARBDB server '%s', please start one or add a filename",path);
1005    }
1006   
1007    gbd->server_id = 0;
1008    gb_main->remote_hash = GBS_create_hashi(GB_REMOTE_HASH_SIZE);
1009
1010    if (gb_init_transaction(gbd))       {       /* login in server */
1011                return GB_get_error();
1012    }
1013    gbd->flags2.folded_container = 1;
1014
1015    if (        strchr(opent, 't')      ) gb_unfold(gbd,0,-2);  /* tiny */
1016    else if (strchr(opent, 'm') ) gb_unfold(gbd,1,-2);  /* medium (no sequence)*/
1017    else if (strchr(opent, 'b') ) gb_unfold(gbd,2,-2);  /* big (no tree)*/
1018    else if (strchr(opent, 'h') ) gb_unfold(gbd,-1,-2); /* huge (all)*/
1019    else gb_unfold(gbd,0,-2);   /* tiny */
1020    return 0;
1021}
1022
1023GBDATA *GB_login(const char *path,const char *opent,const char *user)
1024     /* opent   char    'r'     read
1025                                        'w'     write
1026                                        'c'     create
1027                                        'd'     look for default (if create)
1028                                                in $ARBHOME/lib
1029                                                        (any leading '.' is removed )
1030                                        'D'     look for default (if create)
1031                                                in $ARBHOME/lib/arb_default
1032                                                        (any leading '.' is removed )
1033                                        't'     small memory usage
1034                                        'm'     medium
1035                                        'h'     huge
1036
1037                                        'R'     allow corrupt file recovery + opening quicks with no master
1038                */
1039{
1040    GBCONTAINER         *gbd;
1041    FILE           *input;
1042    long             i;
1043    char                *free_path = 0;
1044    struct gb_main_type *Main;
1045    enum gb_open_types opentype;
1046    GB_CSTR quickFile = NULL;
1047    int ignoreMissingMaster = 0;
1048    int loadedQuickIndex = -1;
1049    GB_ERROR    error = 0;
1050
1051   
1052    if (!opent) opentype = gb_open_all;
1053    else if (strchr(opent, 'w')) opentype = gb_open_all;
1054    else if (strchr(opent, 's')) opentype = gb_open_read_only_all;
1055    else opentype = gb_open_read_only_all;
1056
1057    if (strchr(path,':')){
1058                ; /* remote access */
1059    }else if (GBS_string_cmp(path,"*.quick?",0)==0){
1060                char *ext = gb_findExtension(path);
1061                ad_assert(ext!=0);
1062                if (isdigit(ext[6]))
1063                {
1064                        loadedQuickIndex = atoi(ext+6);
1065                        strcpy(ext, ".arb");
1066                        quickFile = gb_oldQuicksaveName(path, loadedQuickIndex);
1067                        if (strchr(opent,'R'))          ignoreMissingMaster = 1;
1068                }
1069    }else if (GBS_string_cmp(path,"*.a??",0)==0){
1070       
1071                char *extension = gb_findExtension(path);
1072
1073                if (isdigit(extension[2]) && isdigit(extension[3]))
1074                {
1075                        loadedQuickIndex = atoi(extension+2);
1076                        strcpy(extension,".arb");
1077                        quickFile = gb_quicksaveName(path, loadedQuickIndex);
1078                        if (strchr(opent,'R'))          ignoreMissingMaster = 1;
1079                }else {
1080                        char *base = GB_STRDUP(path);
1081                        char *ext = gb_findExtension(base);
1082                        {
1083                                struct gb_scandir dir;
1084                                ext[0]=0;
1085                                gb_scan_directory(base,&dir);
1086                                loadedQuickIndex = dir.highest_quick_index;
1087
1088                                if (dir.highest_quick_index!=dir.newest_quick_index)
1089                                {
1090                                        GB_warning("The QuickSave-File with the highest index-number\n"
1091                                                           "is not the NEWEST of your QuickSave-Files.\n"
1092                                                           "If you didn't restore old QuickSave-File from a backup\n"
1093                                                           "please inform your system-administrator - \n"
1094                                                           "this may be a serious bug and you may loose your data.");
1095                                }
1096
1097                                switch(dir.type)
1098                                {
1099                                        case GB_SCAN_NO_QUICK:
1100                                                break;
1101                                        case GB_SCAN_NEW_QUICK:
1102                                                quickFile = gb_quicksaveName(path,dir.highest_quick_index);
1103                                                break;
1104                                        case GB_SCAN_OLD_QUICK:
1105                                                quickFile = gb_oldQuicksaveName(path,dir.newest_quick_index);
1106                   
1107                                                break;
1108                                }
1109                        }
1110
1111                        free(base);
1112                }
1113    }
1114   
1115    if (gb_verbose_mode){
1116                fprintf(stdout, "       ARB:    Loading '%s' ", path);
1117                if (quickFile) fprintf(stdout, "+ Changes-File '%s'", quickFile);
1118                fprintf(stdout,"\n");
1119    }
1120   
1121    gbm_init_mem();
1122    gb_init_gb();
1123     
1124    if (GB_install_pid(1)) return 0;
1125
1126    Main = gb_make_gb_main_type(path);
1127    Main->local_mode = GB_TRUE;
1128
1129    if (strchr(opent,'R')) Main->allow_corrupt_file_recovery = 1;
1130
1131    gb_create_key(Main,"main",GB_FALSE);
1132
1133    Main->dummy_father = gb_make_container(NULL, 0, -1,0);      /* create "main" */
1134    Main->dummy_father->main_idx = gb_make_main_idx(Main);
1135    Main->dummy_father->server_id = GBTUM_MAGIC_NUMBER;
1136    gbd = gb_make_container(Main->dummy_father, 0, -1,0 );      /* create "main" */
1137
1138    Main->data = gbd;
1139    gbcm_login(gbd,user);
1140    Main->opentype = opentype;
1141    Main->security_level = 7;
1142
1143
1144   
1145    if (path && (strchr(opent, 'r')) ){
1146                if (strchr(path, ':')){
1147                        error = gb_login_remote(Main,path,opent);
1148                }else{
1149                        GB_ULONG time_of_main_file = 0;
1150                        GB_ULONG time_of_quick_file = 0;
1151                        Main->local_mode = GB_TRUE;
1152                        GB_begin_transaction((GBDATA *)gbd);
1153                        Main->clock = 0;                /* start clock */
1154                        input = fopen(path, "r");
1155                        if (!input && ignoreMissingMaster){
1156                                goto load_quick_save_file_only;
1157                        }
1158           
1159                        if ( !input ) 
1160                        {
1161                                GB_disable_quicksave((GBDATA *)gbd,"Database Created");
1162
1163                                if (strchr(opent, 'c') )
1164                                {
1165                                        if (strchr(opent, 'd')||strchr(opent, 'D')){
1166                                                /* use default settings */
1167                                                const char *pre;
1168                                                if (strchr(opent, 'd')) pre = "";
1169                                                else pre = "arb_default/";
1170                                                free_path = GBS_find_lib_file(path,pre);
1171                                                if (!free_path) {
1172                                                        fprintf(stderr,"file %s not found\n", path);
1173                                                        fprintf(stderr,"Looking for default file %s, but not found in $ARBHOME/lib/%s\n",path,pre);
1174                                                        fprintf(stderr," database %s created\n", path);
1175                                                        GB_commit_transaction((GBDATA *)gbd);
1176                                                        return (GBDATA *)gbd;
1177                                                }
1178                                                path = free_path;
1179                                                input = fopen(path, "r");
1180                                        }else{ 
1181                                                printf(" database %s created\n", path);
1182                                                GB_commit_transaction((GBDATA *)gbd);
1183                                                return (GBDATA *)gbd;
1184                                        }
1185                                }else{
1186                                        GB_export_error("ERROR Database '%s' not found",path);
1187                                        return 0;
1188                                }
1189                        }
1190                        time_of_main_file = GB_time_of_file(path);
1191                        i = gb_read_in_long(input, 0);
1192                        if ((i== 0x56430176) || (i == GBTUM_MAGIC_NUMBER) || (i == GBTUM_MAGIC_REVERSED))    {
1193                                i = gb_read_bin(input, gbd,0);          /* read or map whole db */
1194                                gbd = Main->data;
1195                                fclose(input);
1196                   
1197                                /* gb_testDB((GBDATA*)gbd); */
1198
1199                                if (i ){
1200                                        if (Main->allow_corrupt_file_recovery) {
1201                                                GB_print_error();
1202                                        }else{
1203                                                return 0;
1204                                        }
1205                                }
1206               
1207                                if (quickFile){
1208                                        long err;
1209                                load_quick_save_file_only:
1210                                        err = 0;
1211                                        input = fopen(quickFile,"r");
1212
1213                                        if (input){
1214                                                time_of_quick_file = GB_time_of_file(quickFile);
1215                                                if (time_of_main_file && time_of_quick_file < time_of_main_file){
1216                                                        GB_export_error("Your main database file '%s' is newer than\n"
1217                                                                                        "       the changes file '%s'\n"
1218                                                                                        "       That is very strange and happens only if files where\n"
1219                                                                                        "       moved/copied by hand\n"
1220                                                                                        "       Your file '%s' may be an old relict,\n"
1221                                                                                        "       if you ran into problems now,delete it",
1222                                                                                        path,quickFile,quickFile);
1223                                                        GB_print_error();
1224                                                        GB_warning(GB_get_error());
1225                                                }
1226                                                i = gb_read_in_long(input, 0);
1227                                                if ((i== 0x56430176) || (i == GBTUM_MAGIC_NUMBER) || (i == GBTUM_MAGIC_REVERSED)) 
1228                                                {
1229                                                        err = gb_read_bin(input, gbd, 1);
1230                                                        fclose (input);
1231                                                }
1232                                        }   else err = 1;
1233
1234                                        if (err){
1235                                                GB_export_error("I cannot load your quick file '%s';\n"
1236                                                                                "    you may restore an older version by running arb with:\n"
1237                                                                                "    arb <name of quicksave-file>",
1238                                                                                quickFile);
1239                                                GB_print_error();
1240                                                if (Main->allow_corrupt_file_recovery){
1241                                                        return (GBDATA *)(gbd);
1242                                                }
1243                                                return 0;
1244                                        }
1245                                }
1246                                Main->qs.last_index = loadedQuickIndex; /* determines which # will be saved next */
1247                        } else {
1248                                fclose(input);
1249                                (void) gb_read_ascii(path, gbd);
1250                                GB_disable_quicksave((GBDATA *)gbd,"Sorry, I cannot save differences to ascii files\n"
1251                                                                         "      Save whole database in binary mode first");
1252                        }
1253                }
1254    }else{
1255                GB_disable_quicksave((GBDATA *)gbd,"Database not part of this process");
1256                Main->local_mode = GB_TRUE;
1257                GB_begin_transaction((GBDATA *)gbd);
1258    }
1259    if (error) return 0;
1260    GB_commit_transaction((GBDATA *)gbd);
1261    {                           /* New Transaction, should be quicksaveable */
1262                GB_begin_transaction((GBDATA *)gbd);
1263                if (!strchr(opent,'N')){        /* new format */
1264                        gb_convert_V2_to_V3((GBDATA *)gbd);             /* Compression conversion */
1265                }
1266                error = gb_load_key_data_and_dictionaries((GBDATA *)Main->data);
1267                if (!error){
1268                        error = GB_resort_system_folder_to_top((GBDATA *)Main->data);
1269                }
1270                GB_commit_transaction((GBDATA *)gbd);
1271    }
1272    Main->security_level = 0;
1273    gbl_install_standard_commands((GBDATA *)gbd);
1274    if (gb_verbose_mode)    fprintf(stdout, "   ARB:    Loading '%s' done\n", path);
1275    if (free_path) free(free_path);
1276    return (GBDATA *)gbd;
1277}
1278
1279GBDATA *GB_open(const char *path, const char *opent)
1280{
1281    const char *user;
1282    user = GB_getenvUSER();
1283    return GB_login(path,opent,user);
1284}
1285
1286int gb_verbose_mode = 0;
1287
1288void GB_set_verbose(){
1289    gb_verbose_mode = 1;
1290}
Note: See TracBrowser for help on using the repository browser.