00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00056 #include <stdio.h>
00057 #include <time.h>
00058 #include <errno.h>
00059 #include <sys/types.h>
00060 #include <dirent.h>
00061 #include <unistd.h>
00062 #include <stdlib.h>
00063
00064 #include "bin.h"
00065
00066
00070 #define BIN_DEBUG 0
00071
00077 #define BIN_DECODE_CHECKS 1
00078
00079 inline int bin_alloc(bin_data *x, int max_len)
00080 {
00081 x->s = (char*)BIN_ALLOC_METHOD(max_len);
00082 if (!x->s){
00083 LOG(L_ERR,"ERR:"M_NAME":bin_alloc: Error allocating %d bytes.\n",max_len);
00084 x->len=0;
00085 x->max=0;
00086 return 0;
00087 }
00088 x->len=0;
00089 x->max=max_len;
00090 return 1;
00091 }
00092
00093 inline int bin_realloc(bin_data *x, int delta)
00094 {
00095 #if BIN_DEBUG
00096 LOG(L_INFO,"INFO:"M_NAME":bin_realloc: realloc %p from %d to + %d\n",x->s,x->max,delta);
00097 #endif
00098 x->s=BIN_REALLOC_METHOD(x->s,x->max + delta);
00099 if (x->s==NULL){
00100 LOG(L_ERR,"ERR:"M_NAME":bin_realloc: No more memory to expand %d with %d \n",x->max,delta);
00101 return 0;
00102 }
00103 x->max += delta;
00104 return 1;
00105 }
00106
00107 inline int bin_expand(bin_data *x, int delta)
00108 {
00109 if (x->max-x->len>=delta) return 1;
00110 #if BIN_DEBUG
00111 LOG(L_INFO,"INFO:"M_NAME":bin_realloc: realloc %p from %d to + %d\n",x->s,x->max,delta);
00112 #endif
00113 x->s=BIN_REALLOC_METHOD(x->s,x->max + delta);
00114 if (x->s==NULL){
00115 LOG(L_ERR,"ERR:"M_NAME":bin_realloc: No more memory to expand %d with %d \n",x->max,delta);
00116 return 0;
00117 }
00118 x->max += delta;
00119 return 1;
00120 }
00121
00122 inline void bin_free(bin_data *x)
00123 {
00124 BIN_FREE_METHOD(x->s);
00125 x->s=0;x->len=0;x->max=0;
00126 }
00127
00131 inline void bin_print(bin_data *x)
00132 {
00133 int i,j,w=16;
00134 char c;
00135 fprintf(stderr,"----------------------------------\nBinary form %d (max %d) bytes:\n",x->len,x->max);
00136 for(i=0;i<x->len;i+=w){
00137 fprintf(stderr,"%04X> ",i);
00138 for(j=0;j<w;j++){
00139 if (i+j<x->len) fprintf(stderr,"%02X ",(unsigned char)x->s[i+j]);
00140 else fprintf(stderr," ");
00141 }
00142 printf("\t");
00143 for(j=0;j<w;j++)if (i+j<x->len){
00144 if (x->s[i+j]>32) c=x->s[i+j];
00145 else c = '.';
00146 fprintf(stderr,"%c",c);
00147 }else fprintf(stderr," ");
00148 fprintf(stderr,"\n");
00149 }
00150 fprintf(stderr,"\n---------------------------------\n");
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00167 inline int bin_encode_char(bin_data *x,char k)
00168 {
00169 if (!bin_expand(x,1)) return 0;
00170 x->s[x->len++]= k;
00171 #if BIN_DEBUG
00172 LOG(L_INFO,"INFO:"M_NAME":bin_encode_char: [%d]:[%.02x] new len %04x\n",k,x->s[x->len-1],x->len);
00173 #endif
00174 return 1;
00175 }
00179 inline int bin_decode_char(bin_data *x,char *c)
00180 {
00181 #if BIN_DECODE_CHECKS
00182 if (x->max+1 > x->len) return 0;
00183 #endif
00184 *c = x->s[x->max];
00185 x->max += 1;
00186 #if BIN_DEBUG
00187 LOG(L_INFO,"INFO:"M_NAME":bin_decode_char: [%d] new pos %04x\n",*c,x->max);
00188 #endif
00189 return 1;
00190 }
00191
00192
00193
00194
00198 inline int bin_encode_uchar(bin_data *x,unsigned char k)
00199 {
00200 if (!bin_expand(x,1)) return 0;
00201 x->s[x->len++]= k;
00202 #if BIN_DEBUG
00203 LOG(L_INFO,"INFO:"M_NAME":bin_encode_uchar: [%u]:[%.02x] new len %04x\n",k,x->s[x->len-1],x->len);
00204 #endif
00205 return 1;
00206 }
00210 inline int bin_decode_uchar(bin_data *x,unsigned char *c)
00211 {
00212 #if BIN_DECODE_CHECKS
00213 if (x->max+1 > x->len) return 0;
00214 #endif
00215 *c = x->s[x->max];
00216 x->max += 1;
00217 #if BIN_DEBUG
00218 LOG(L_INFO,"INFO:"M_NAME":bin_decode_uchar: [%u] new pos %04x\n",*c,x->max);
00219 #endif
00220 return 1;
00221 }
00222
00223
00224
00225
00226
00227
00228
00232 inline int bin_encode_short(bin_data *x,short k)
00233 {
00234 if (!bin_expand(x,2)) return 0;
00235 x->s[x->len++]=k & 0x00FF;
00236 x->s[x->len++]=(k & 0xFF00) >> 8;
00237 #if BIN_DEBUG
00238 LOG(L_INFO,"INFO:"M_NAME":bin_encode_short: [%d]:[%.02x %.02x] new len %04x\n",k,x->s[x->len-2],x->s[x->len-1],x->len);
00239 #endif
00240 return 1;
00241 }
00245 inline int bin_decode_short(bin_data *x,short *v)
00246 {
00247 #if BIN_DECODE_CHECKS
00248 if (x->max+2 > x->len) return 0;
00249 #endif
00250 *v = (unsigned char)x->s[x->max ] |
00251 (unsigned char)x->s[x->max+1]<<8;
00252 x->max += 2;
00253 #if BIN_DEBUG
00254 LOG(L_INFO,"INFO:"M_NAME":bin_decode_short: [%d] new pos %04x\n",*v,x->max);
00255 #endif
00256 return 1;
00257 }
00258
00259
00263 inline int bin_encode_ushort(bin_data *x,unsigned short k)
00264 {
00265 if (!bin_expand(x,2)) return 0;
00266 x->s[x->len++]=k & 0x00FF;
00267 x->s[x->len++]=(k & 0xFF00) >> 8;
00268 #if BIN_DEBUG
00269 LOG(L_INFO,"INFO:"M_NAME":bin_encode_ushort: [%u]:[%.02x %.02x] new len %04x\n",k,x->s[x->len-2],x->s[x->len-1],x->len);
00270 #endif
00271 return 1;
00272 }
00276 inline int bin_decode_ushort(bin_data *x,unsigned short *v)
00277 {
00278 #if BIN_DECODE_CHECKS
00279 if (x->max+2 > x->len) return 0;
00280 #endif
00281 *v = (unsigned char)x->s[x->max ] |
00282 (unsigned char)x->s[x->max+1]<<8;
00283 x->max += 2;
00284 #if BIN_DEBUG
00285 LOG(L_INFO,"INFO:"M_NAME":bin_decode_ushort: [%u] new pos %04x\n",*v,x->max);
00286 #endif
00287 return 1;
00288 }
00289
00290
00294 inline int bin_encode_int(bin_data *x,int k)
00295 {
00296 int len = sizeof(int),i;
00297 if (!bin_expand(x,len)) return 0;
00298 for(i=0;i<len;i++){
00299 x->s[x->len++]= k & 0xFF;
00300 k = k>>8;
00301 }
00302 #if BIN_DEBUG
00303 switch(len){
00304 case 4:
00305 LOG(L_INFO,"INFO:"M_NAME":bin_encode_int: [%d]:[%.02x %.02x %.02x %.02x] new len %04x\n",k,
00306 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],x->len);
00307 break;
00308 case 8:
00309 LOG(L_INFO,"INFO:"M_NAME":bin_encode_int: [%d]:[%.02x %.02x %.02x %.02x%.02x %.02x %.02x %.02x] new len %04x\n",k,
00310 x->s[x->len-8],x->s[x->len-7],x->s[x->len-6],x->s[x->len-5],
00311 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],
00312 x->len);
00313 break;
00314 }
00315 #endif
00316 return 1;
00317 }
00321 inline int bin_decode_int(bin_data *x,int *v)
00322 {
00323 int len = sizeof(int),i;
00324 #if BIN_DECODE_CHECKS
00325 if (x->max+len > x->len) return 0;
00326 #endif
00327 *v = 0;
00328 for(i=0;i<len;i++)
00329 *v = *v | ((unsigned char)x->s[x->max++] <<(8*i));
00330 #if BIN_DEBUG
00331 LOG(L_INFO,"INFO:"M_NAME":bin_decode_int: [%d] new pos %04x\n",*v,x->max);
00332 #endif
00333 return 1;
00334 }
00335
00336
00337
00341 inline int bin_encode_uint(bin_data *x,unsigned int k)
00342 {
00343 int len = sizeof(unsigned int),i;
00344 if (!bin_expand(x,len)) return 0;
00345 for(i=0;i<len;i++){
00346 x->s[x->len++]= k & 0xFF;
00347 k = k>>8;
00348 }
00349 #if BIN_DEBUG
00350 switch(len){
00351 case 4:
00352 LOG(L_INFO,"INFO:"M_NAME":bin_encode_uint: [%u]:[%.02x %.02x %.02x %.02x] new len %04x\n",k,
00353 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],x->len);
00354 break;
00355 case 8:
00356 LOG(L_INFO,"INFO:"M_NAME":bin_encode_uint: [%u]:[%.02x %.02x %.02x %.02x%.02x %.02x %.02x %.02x] new len %04x\n",k,
00357 x->s[x->len-8],x->s[x->len-7],x->s[x->len-6],x->s[x->len-5],
00358 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],
00359 x->len);
00360 break;
00361 }
00362 #endif
00363 return 1;
00364 }
00368 inline int bin_decode_uint(bin_data *x,unsigned int *v)
00369 {
00370 int len = sizeof(unsigned int),i;
00371 #if BIN_DECODE_CHECKS
00372 if (x->max+len > x->len) return 0;
00373 #endif
00374 *v = 0;
00375 for(i=0;i<len;i++)
00376 *v = *v | ((unsigned char)x->s[x->max++] <<(8*i));
00377 #if BIN_DEBUG
00378 LOG(L_INFO,"INFO:"M_NAME":bin_decode_uint: [%u] new pos %04x\n",*v,x->max);
00379 #endif
00380 return 1;
00381 }
00382
00386 inline int bin_encode_time_t(bin_data *x,time_t k)
00387 {
00388 int len = sizeof(time_t),i;
00389 if (!bin_expand(x,len)) return 0;
00390 for(i=0;i<len;i++){
00391 x->s[x->len++]= k & 0xFF;
00392 k = k>>8;
00393 }
00394 #if BIN_DEBUG
00395 switch(len){
00396 case 4:
00397 LOG(L_INFO,"INFO:"M_NAME":bin_encode_time_t: [%u]:[%.02x %.02x %.02x %.02x] new len %04x\n",(unsigned int)k,
00398 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],x->len);
00399 break;
00400 case 8:
00401 LOG(L_INFO,"INFO:"M_NAME":bin_encode_time_t: [%u]:[%.02x %.02x %.02x %.02x%.02x %.02x %.02x %.02x] new len %04x\n",(unsigned int)k,
00402 x->s[x->len-8],x->s[x->len-7],x->s[x->len-6],x->s[x->len-5],
00403 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],
00404 x->len);
00405 break;
00406 }
00407 #endif
00408 return 1;
00409 }
00413 inline int bin_decode_time_t(bin_data *x,time_t *v)
00414 {
00415 int len = sizeof(time_t),i;
00416 #if BIN_DECODE_CHECKS
00417 if (x->max+len > x->len) return 0;
00418 #endif
00419 *v = 0;
00420 for(i=0;i<len;i++)
00421 *v = *v | ((unsigned char)x->s[x->max++] <<(8*i));
00422 #if BIN_DEBUG
00423 LOG(L_INFO,"INFO:"M_NAME":bin_decode_time_t: [%u] new pos %04x\n",(unsigned int) *v,x->max);
00424 #endif
00425 return 1;
00426 }
00427
00428
00432 inline int bin_encode_str(bin_data *x,str *s)
00433 {
00434 if (!bin_expand(x,2+s->len)) return 0;
00435 if (s->len>65535)
00436 LOG(L_ERR,"ERROR:"M_NAME":bin_encode_str: Possible loss of characters in encoding (string > 65535bytes) %d bytes \n",s->len);
00437 x->s[x->len++]=s->len & 0x000000FF;
00438 x->s[x->len++]=(s->len & 0x0000FF00)>>8;
00439 memcpy(x->s+x->len,s->s,s->len);
00440 x->len+=s->len;
00441 #if BIN_DEBUG
00442 LOG(L_INFO,"INFO:"M_NAME":bin_encode_str : [%d]:[%.02x %.02x]:[%.*s] new len %04x\n",s->len,
00443 x->s[x->len-s->len-2],x->s[x->len-s->len-1],s->len,s->s,x->len);
00444 #endif
00445 return 1;
00446 }
00450 inline int bin_decode_str(bin_data *x,str *s)
00451 {
00452 #if BIN_DECODE_CHECKS
00453 if (x->max+2 > x->len) return 0;
00454 #endif
00455 s->len = (unsigned char)x->s[x->max ] |
00456 (unsigned char)x->s[x->max+1]<<8;
00457 x->max +=2;
00458 if (x->max+s->len>x->len) return 0;
00459 s->s = x->s + x->max;
00460 x->max += s->len;
00461 #if BIN_DEBUG
00462 LOG(L_INFO,"INFO:"M_NAME":bin_decode_str : [%d]:[%.*s] new pos %04x\n",s->len,s->len,s->s,x->max);
00463 #endif
00464 return 1;
00465 }
00466
00467
00468
00469
00470
00471
00472
00473 extern dlg_func_t dialogb;
00482 int bin_encode_dlg_t(bin_data *x,dlg_t *d)
00483 {
00484 str s={0,0};
00485 if (d){
00486 if (dialogb.dlg2str(d,&s)!=0) goto error;
00487 }
00488 if (!bin_encode_str(x,&s)) goto error;
00489 str_free_content(&s);
00490 return 1;
00491 error:
00492 LOG(L_ERR,"ERR:"M_NAME":bin_encode_dlg_t: Error while encoding.\n");
00493 if (s.s) str_free_content(&s);
00494 return 0;
00495 }
00496
00503 int bin_decode_dlg_t(bin_data *x,dlg_t **d)
00504 {
00505 int len;
00506 str s;
00507
00508 if (!bin_decode_str(x,&s)) goto error;
00509
00510 if (!s.len) {
00511 *d = 0;
00512 return 1;
00513 }
00514
00515 len = sizeof(dlg_t);
00516 *d = (dlg_t*) shm_malloc(len);
00517 if (!*d) {
00518 LOG(L_ERR,"ERR:"M_NAME":bin_decode_dlg_t: Error allocating %d bytes.\n",len);
00519 goto error;
00520 }
00521 memset(*d,0,len);
00522 if (dialogb.str2dlg(&s,*d)!=0) goto error;
00523
00524 return 1;
00525 error:
00526 LOG(L_ERR,"ERR:"M_NAME":bin_decode_dlg_t: Error while decoding (at %d (%04x)).\n",x->max,x->max);
00527 if (*d) {
00528 shm_free(*d);
00529 }
00530 return 0;
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540 int bin_files_keep_count=3;
00553 int bin_dump_to_file(bin_data *x,char *location,char *prepend_fname)
00554 {
00555 char c_part[256],c_time[256],c_last[256];
00556 time_t now;
00557 FILE *f;
00558 int k;
00559
00560 now = time(0);
00561 sprintf(c_part,"%s/%s_%.10u.bin.part",location,prepend_fname,(unsigned int)now);
00562 sprintf(c_time,"%s/%s_%.10u.bin",location,prepend_fname,(unsigned int)now);
00563 sprintf(c_last,"%s/_%s.bin",location,prepend_fname);
00564
00565
00566 f = fopen(c_part,"w");
00567 if (!f){
00568 LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when opening file <%s> for writting [%s]\n",c_part,strerror(errno));
00569 return 0;
00570 }
00571 k = fwrite(x->s,1,x->len,f);
00572 LOG(L_INFO,"INFO:"M_NAME":bin_dump_to_file: Dumped %d bytes into %s.\n",k,c_part);
00573 fclose(f);
00574
00575
00576 if (rename(c_part,c_time)<0){
00577 LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when renaming <%s> -> <%s> [%s]\n",c_part,c_time,strerror(errno));
00578 return 0;
00579 }
00580
00581
00582 if (k==x->len) {
00583 if (remove(c_last)<0 && errno!=ENOENT){
00584 LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when removing symlink <%s> [%s]\n",c_last,strerror(errno));
00585 return 0;
00586 }
00587 if (symlink(c_time,c_last)<0){
00588 LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when symlinking <%s> -> <%s> [%s]\n",c_time,c_last,strerror(errno));
00589 return 0;
00590 }
00591
00592 {
00593 struct dirent **namelist;
00594 int i,n,k=bin_files_keep_count;
00595 int len=strlen(prepend_fname);
00596 n = scandir(location,&namelist,0,alphasort);
00597 if (n>0){
00598 for(i=n-1;i>=0;i--){
00599 if (strlen(namelist[i]->d_name)>len &&
00600 memcmp(namelist[i]->d_name,prepend_fname,len)==0) {
00601 if (k) k--;
00602 else {
00603 sprintf(c_part,"%s/%s",location,namelist[i]->d_name);
00604 remove(c_part);
00605 }
00606 }
00607 free(namelist[i]);
00608 }
00609 free(namelist);
00610 }
00611 }
00612 return 1;
00613 }
00614 else return 0;
00615 }
00616
00617
00624 int bin_load_from_file(bin_data *x,char *location,char *prepend_fname)
00625 {
00626 char c[256];
00627 FILE *f;
00628 int k;
00629
00630 sprintf(c,"%s/_%s.bin",location,prepend_fname);
00631 f = fopen(c,"r");
00632 if (!f) {
00633 LOG(L_ERR,"ERR:"M_NAME":bin_load_from_file: error opening %s : %s\n",c,strerror(errno));
00634 return 0;
00635 }
00636 bin_alloc(x,1024);
00637 while(!feof(f)){
00638 bin_expand(x,1024);
00639 k = fread(x->s+x->len,1,1024,f);
00640 x->len+=k;
00641 }
00642 LOG(L_INFO,"INFO:"M_NAME":bin_load_from_file: Read %d bytes from %s.\n",x->len,c);
00643 fclose(f);
00644 return 1;
00645 }
00646
00647
00655 int bin_dump(bin_data *x,int mode,char *location,char* prepend_fname)
00656 {
00657 switch (mode){
00658 case NO_PERSISTENCY:
00659 LOG(L_ERR,"ERR:"M_NAME":bin_dump: Snapshot done but persistency was disabled...\n");
00660 return 0;
00661 case WITH_FILES:
00662 return bin_dump_to_file(x,location,prepend_fname);
00663
00664
00665
00666
00667
00668 default:
00669 LOG(L_ERR,"ERR:"M_NAME":bin_dump: Snapshot done but no such mode %d\n",mode);
00670 return 0;
00671 }
00672 }
00673
00680 int bin_load(bin_data *x,int mode,char *location,char* prepend_fname)
00681 {
00682 switch (mode){
00683 case NO_PERSISTENCY:
00684 LOG(L_ERR,"ERR:"M_NAME":bin_load: Persistency support was disabled\n");
00685 return 0;
00686 case WITH_FILES:
00687 return bin_load_from_file(x,location,prepend_fname);
00688
00689
00690
00691
00692
00693
00694 default:
00695 LOG(L_ERR,"ERR:"M_NAME":bin_load: Can't resume because no such mode %d\n",mode);
00696 return 0;
00697 }
00698 }
00699
00700
00701
00702