revert between 56095 -> 55830 in arch
[AROS.git] / rom / filesys / SFS / FS / support.c
blob8304292876e5a56f6fc00f22c2fcd4ea1c7998cf
1 #include "asmsupport.h"
3 #include <dos/dos.h>
4 #include <dos/bptr.h>
5 #include <exec/types.h>
6 #include <exec/lists.h>
7 #include <proto/dos.h>
8 #include <proto/exec.h>
10 #include <strings.h>
12 #include "sysdep.h"
13 #include "blockstructure.h"
14 #include "fs.h"
16 #include "globals.h"
17 #include "debug.h"
19 void ClearMemQuick(void *mem, LONG bytes) {
20 ULONG *m=mem;
22 bytes>>=2;
24 while(--bytes>=0) {
25 *m++=0;
30 #ifdef WORDCOMPRESSION
32 void uncompress(UWORD *dest,UBYTE *data,UWORD length) {
33 UWORD *dataw;
34 UBYTE *end=data+length;
35 UBYTE code,len;
37 /* Decompresses a transaction into /dest/ using /data/ which is
38 /length/ bytes long. */
40 while(data<end) {
41 code=*data++;
43 if((code & 0xC0)==0x40) {
44 /* unchanged data */
45 dest+=(code & 0x3F)+1;
47 else if((code & 0xC0)==0x80) { // else if((code & 0xE0)==0x20) {
48 /* set data */
49 len=(code & 0x3F)+1; // len=(code & 0x1F)+1;
51 while(len--!=0) {
52 *dest++=0xFFFF;
55 else if((code & 0xC0)==0x00) { // else if((code & 0xE0)==0x00) {
56 /* clear data */
57 len=(code & 0x3F)+1; // len=(code & 0x1F)+1;
59 while(len--!=0) {
60 *dest++=0x0000;
63 else {
64 len=(code & 0x3F)+1;
66 dataw=(UWORD *)data;
67 while(len--!=0) {
68 *dest++=*dataw++;
70 data=(UBYTE *)dataw;
78 WORD compress(UWORD *org,UWORD *new,UBYTE *dest) {
79 WORD unchanged,cleared,set,immediate;
80 WORD max;
81 UWORD *o;
82 UWORD *n;
83 UWORD *end=new+(bytes_block>>1);
84 UBYTE *begin=dest;
86 while(new<end) {
87 unchanged=0;
88 cleared=0;
89 set=0;
91 max=end-new;
92 if(max>64) {
93 max=64;
96 o=org;
97 n=new;
99 while(*o++==*n++ && ++unchanged<max) {
102 if(unchanged<max) {
103 n=new;
105 while(*n++==0 && ++cleared<max) {
108 n=new;
110 while(*n++==0xFFFF && ++set<max) {
114 /* Largest of unchanged, cleared and set wins! */
116 if(unchanged!=0 || cleared!=set) {
117 UWORD x;
119 if(unchanged>=cleared && unchanged>=set) {
120 *dest++=0x40+unchanged-1;
121 x=unchanged;
123 else if(cleared!=0) {
124 *dest++=cleared-1;
125 x=cleared;
127 else {
128 *dest++=0x80+set-1; // *dest++=0x20+set-1;
129 x=set;
132 org+=x;
133 new+=x;
135 else {
136 /* Data wasn't unchanged, cleared or set */
138 immediate=0;
140 o=org;
141 n=new;
143 while(*n!=0 && *n!=0xFFFF && *o++!=*n++ && ++immediate<max) {
146 org+=immediate;
148 *dest++=0xC0+immediate-1;
149 o=(UWORD *)dest; /* 68020 only! */
150 while(immediate-->0) {
151 *o++=*new++;
153 dest=(UBYTE *)o;
157 return((WORD)(dest-begin));
162 WORD compressfromzero(UWORD *new,UBYTE *dest) {
163 WORD cleared,set,immediate;
164 WORD max;
165 UWORD *n;
166 UWORD *end=new+(bytes_block>>1);
167 UBYTE *begin=dest;
169 while(new<end) {
170 cleared=0;
171 set=0;
173 max=end-new;
174 if(max>64) {
175 max=64;
178 n=new;
180 while(*n++==0 && ++cleared<max) {
183 n=new;
185 while(*n++==0xFFFF && ++set<max) {
188 /* Largest of cleared and set wins! */
190 if(cleared!=set) {
191 UWORD x;
193 if(cleared!=0) {
194 *dest++=cleared-1;
195 x=cleared;
197 else {
198 *dest++=0x80+set-1; // *dest++=0x20+set-1;
199 x=set;
202 new+=x;
204 else {
205 /* Data wasn't cleared or set */
207 immediate=0;
209 n=new;
211 while(*n!=0 && *n++!=0xFFFF && ++immediate<max) {
214 *dest++=0xC0+immediate-1;
215 n=(UWORD *)dest; /* 68020 only! */
216 while(immediate-->0) {
217 *n++=*new++;
219 dest=(UBYTE *)n;
223 return((WORD)(dest-begin));
226 #endif
229 #ifdef LONGCOMPRESSION
231 void uncompress(ULONG *dest,UBYTE *data,UWORD length) {
232 ULONG *dataw;
233 UBYTE *end=data+length;
234 UBYTE code,len;
236 /* Decompresses a transaction into /dest/ using /data/ which is
237 /length/ bytes long. */
239 while(data<end) {
240 code=*data++;
242 if((code & 0xC0)==0x40) {
243 /* unchanged data */
244 dest+=(code & 0x3F)+1;
246 else if((code & 0xC0)==0x80) { // else if((code & 0xE0)==0x20) {
247 /* set data */
248 len=(code & 0x3F)+1; // len=(code & 0x1F)+1;
250 while(len--!=0) {
251 *dest++=0xFFFFFFFF;
254 else if((code & 0xC0)==0x00) { // else if((code & 0xE0)==0x00) {
255 /* clear data */
256 len=(code & 0x3F)+1; // len=(code & 0x1F)+1;
258 while(len--!=0) {
259 *dest++=0x00000000;
262 else {
263 len=(code & 0x3F)+1;
265 dataw=(ULONG *)data;
266 while(len--!=0) {
267 *dest++=*dataw++;
269 data=(UBYTE *)dataw;
277 WORD compress(ULONG *org,ULONG *new,UBYTE *dest) {
278 WORD unchanged,cleared,set,immediate;
279 WORD max;
280 ULONG *o;
281 ULONG *n;
282 ULONG *end=new+(globals->bytes_block>>2);
283 UBYTE *begin=dest;
285 while(new<end) {
286 unchanged=0;
287 cleared=0;
288 set=0;
290 max=end-new;
291 if(max>64) {
292 max=64;
295 o=org;
296 n=new;
298 while(*o++==*n++ && ++unchanged<max) {
301 if(unchanged<max) {
302 n=new;
304 while(*n++==0 && ++cleared<max) {
307 n=new;
309 while(*n++==0xFFFFFFFF && ++set<max) {
313 /* Largest of unchanged, cleared and set wins! */
315 if(unchanged!=0 || cleared!=set) {
316 UWORD x;
318 if(unchanged>=cleared && unchanged>=set) {
319 *dest++=0x40+unchanged-1;
320 x=unchanged;
322 else if(cleared!=0) {
323 *dest++=cleared-1;
324 x=cleared;
326 else {
327 *dest++=0x80+set-1; // *dest++=0x20+set-1;
328 x=set;
331 org+=x;
332 new+=x;
334 else {
335 /* Data wasn't unchanged, cleared or set */
337 immediate=0;
339 o=org;
340 n=new;
342 while(*n!=0 && *n!=0xFFFFFFFF && *o++!=*n++ && ++immediate<max) {
345 org+=immediate;
347 *dest++=0xC0+immediate-1;
348 o=(ULONG *)dest; /* 68020 only! */
349 while(immediate-->0) {
350 *o++=*new++;
352 dest=(UBYTE *)o;
356 return((WORD)(dest-begin));
361 WORD compressfromzero(ULONG *new,UBYTE *dest) {
362 WORD cleared,set,immediate;
363 WORD max;
364 ULONG *n;
365 ULONG *end=new+(globals->bytes_block>>2);
366 UBYTE *begin=dest;
368 while(new<end) {
369 cleared=0;
370 set=0;
372 max=end-new;
373 if(max>64) {
374 max=64;
377 n=new;
379 while(*n++==0 && ++cleared<max) {
382 n=new;
384 while(*n++==0xFFFFFFFF && ++set<max) {
387 /* Largest of cleared and set wins! */
389 if(cleared!=set) {
390 UWORD x;
392 if(cleared!=0) {
393 *dest++=cleared-1;
394 x=cleared;
396 else {
397 *dest++=0x80+set-1; // *dest++=0x20+set-1;
398 x=set;
401 new+=x;
403 else {
404 /* Data wasn't cleared or set */
406 immediate=0;
408 n=new;
410 while(*n!=0 && *n++!=0xFFFFFFFF && ++immediate<max) {
413 *dest++=0xC0+immediate-1;
414 n=(ULONG *)dest; /* 68020 only! */
415 while(immediate-->0) {
416 *n++=*new++;
418 dest=(UBYTE *)n;
422 return((WORD)(dest-begin));
425 #endif
429 #ifdef NOCOMPRESSION
431 void uncompress(ULONG *dest,UBYTE *data,UWORD length) {
432 CopyMem(data,dest,length);
438 WORD compress(ULONG *org,ULONG *new,UBYTE *dest) {
439 CopyMem(new,dest,bytes_block);
441 return((WORD)bytes_block);
446 WORD compressfromzero(ULONG *new,UBYTE *dest) {
447 CopyMem(new,dest,bytes_block);
449 return((WORD)bytes_block);
452 #endif
455 #ifdef ALTERNATIVECOMPRESSION
457 void uncompress(ULONG *dest, UBYTE *data, UWORD length) {
458 ULONG *datal;
459 ULONG *d;
460 WORD l;
461 UBYTE *dataend=data+length;
463 if(*data++==1) {
464 l=bytes_block>>4;
465 d=dest;
467 while(l-->0) {
468 *d++=0;
469 *d++=0;
470 *d++=0;
471 *d++=0;
475 while(data<dataend) {
476 d=dest + *data++;
477 l=*data++;
479 datal=(ULONG *)data;
481 while(l-->0) {
482 *d++=*datal++;
485 data=(UBYTE *)datal;
491 UWORD compress(ULONG *org, ULONG *new, UBYTE *dest) {
492 ULONG *destl;
493 UWORD longs_block=bytes_block>>2;
494 UWORD longsleft=longs_block;
495 UBYTE count;
496 UBYTE *deststart=dest;
498 *dest++=0;
500 for(;;) {
501 while(*org==*new) {
502 org++;
503 new++;
504 if(--longsleft==0) {
505 return((UWORD)(dest-deststart));
509 *dest++=longs_block-longsleft;
510 destl=(ULONG *)(dest+1);
511 count=0;
513 do {
514 count++;
515 org++;
516 *destl++=*new++;
517 if(--longsleft==0) {
518 *dest=count;
519 dest=(UBYTE *)destl;
520 return((UWORD)(dest-deststart));
522 } while(*org!=*new);
524 *dest=count;
525 dest=(UBYTE *)destl;
531 UWORD compressfromzero(ULONG *new, UBYTE *dest) {
532 ULONG *destl;
533 UWORD longs_block=bytes_block>>2;
534 UWORD longsleft=longs_block;
535 UBYTE count;
536 UBYTE *deststart=dest;
538 *dest++=1;
540 for(;;) {
541 while(*new==0) {
542 new++;
543 if(--longsleft==0) {
544 return((UWORD)(dest-deststart));
548 *dest++=longs_block-longsleft;
549 destl=(ULONG *)(dest+1);
550 count=0;
552 do {
553 count++;
554 *destl++=*new++;
555 if(--longsleft==0) {
556 *dest=count;
557 dest=(UBYTE *)destl;
558 return((UWORD)(dest-deststart));
560 } while(*new!=0);
562 *dest=count;
563 dest=(UBYTE *)destl;
567 #endif
571 UBYTE *stripcolon(UBYTE *path) {
572 UBYTE *path2;
574 /* Finds the last colon in the path string (if any) and returns a pointer
575 to the character following it. If no colon is found you get a pointer
576 to the first character in the string. */
578 path2=path;
579 while(*path2!=0) {
580 if(*path2++==':') {
581 path=path2;
584 return(path);
589 UBYTE upperchar(UBYTE c) {
590 if((c>=224 && c<=254 && c!=247) || (c>='a' && c<='z')) {
591 c-=32;
593 return(c);
598 UWORD hash(UBYTE *name, WORD casesensitive) {
599 UWORD hash=0;
601 /* Calculates a hash value over the passed in string. The end of the string
602 can be either a NUL byte or a slash. The hash function is the same as the
603 one used in FastFileSystem set to international mode. */
605 while(name[hash]!=0 && name[hash]!='/') {
606 hash++;
609 if(casesensitive==FALSE) {
610 while(*name!=0 && *name!='/') {
611 hash=hash*13+upperchar(*name++);
614 else {
615 while(*name!=0 && *name!='/') {
616 hash=hash*13+*name++;
620 return(hash);
624 UBYTE *validatepath(UBYTE *string) {
625 UBYTE *d;
626 UBYTE *r;
627 UBYTE c;
628 WORD cnt;
630 /* This functions limits the length of any path-part of the passed in string
631 to max_name_length characters. It also strips the colons. */
633 string=stripcolon(string);
635 d=string;
636 r=string;
638 cnt=globals->max_name_length;
640 while((c=*string++)!=0) {
641 if(c=='/') {
642 cnt=globals->max_name_length+1;
644 if(--cnt>=0) {
645 *d++=c;
649 *d=0;
651 return(r);
656 BYTE isvalidcomponentname(UBYTE *name) {
657 UBYTE c;
659 /* This function returns FALSE if the passed name
660 is empty or contains a slash or colon. */
662 if(name==0 || *name==0) {
663 return(FALSE);
666 while((c=*name++)!=0) {
667 if(c==':' || c=='/') {
668 return(FALSE);
672 return(TRUE);
676 void copystr(UBYTE *src,UBYTE *dest,WORD maxlen) {
678 /* maxlen is the maximum stringlength the destination can become, excluding zero
679 termination. */
681 while(--maxlen>=0 && (*dest++=*src++)!=0) {
684 if(maxlen<0) {
685 *dest=0;
691 #ifdef USE_FAST_BSTR
693 UWORD copybstrasstr(BSTR bstr,UBYTE *str,UWORD maxlen)
695 UBYTE *srcstr = BADDR(bstr);
696 UWORD srclen;
698 /* maxlen is the maximum stringlength the destination can become, excluding zero
699 termination. The return value is the length of the destination string also
700 excluding termination. */
702 srclen = strlen(srcstr);
703 if(srclen<maxlen) {
704 maxlen=srclen;
706 srclen=maxlen;
708 while(maxlen--!=0) {
709 *str++ = *srcstr++;
711 *str=0;
713 return(srclen);
716 #else
718 UWORD bstrlen(UBYTE *str) {
719 UWORD len;
721 len=str[0];
722 if(len!=0 && str[len]==0) {
723 len--;
725 return(len);
728 UWORD copybstrasstr(BSTR bstr,UBYTE *str,UWORD maxlen) {
729 UBYTE *srcstr=BADDR(bstr);
730 UWORD srclen=bstrlen(srcstr);
732 /* maxlen is the maximum stringlength the destination can become, excluding zero
733 termination. The return value is the length of the destination string also
734 excluding termination. */
736 srcstr++;
737 if(srclen<maxlen) {
738 maxlen=srclen;
740 srclen=maxlen;
742 while(maxlen--!=0) {
743 *str++=*srcstr++;
745 *str=0;
747 return(srclen);
750 #endif
753 void initlist(struct List *list) {
754 list->lh_Head=(struct Node *)&list->lh_Tail;
755 list->lh_Tail=0;
756 list->lh_TailPred=(struct Node *)list;
762 ULONG datestamptodate(struct DateStamp *datestamp) {
763 return( (ULONG)((UWORD)datestamp->ds_Tick/50) + (ULONG)((UWORD)datestamp->ds_Minute*60) + datestamp->ds_Days*86400 );
768 void datetodatestamp(ULONG date,struct DateStamp *datestamp) {
769 ULONG seconds;
771 datestamp->ds_Days = date/86400;
773 seconds=date - (datestamp->ds_Days * 86400);
775 datestamp->ds_Minute = (ULONG)((UWORD)(seconds/60));
776 datestamp->ds_Tick = (ULONG)((UWORD)(seconds%60)*50);
781 ULONG getdate(void) {
782 struct DateStamp datestamp;
784 DateStamp(&datestamp);
786 return( datestamptodate(&datestamp) );
790 #if 0
792 void mergediffs(ULONG *current, UBYTE *olddiff, UWORD length, UBYTE *newdiff, UWORD *offsets) {
793 ULONG *newdiffl;
794 ULONG *c;
796 *newdiff++=*olddiff++;
798 bytestoskip=*offset & 0x0003;
799 longoffset=(*offsets++)>>2;
801 if(longoffset<*olddiff) {
802 c=current+longoffset;
804 *newdiff++=longoffset;
805 newdiffl=(ULONG *)(newdiff+1);
807 *newdiffl++=*c++;
808 if(bytestoskip!=0) {
809 *newdiffl++=*c++;
810 *newdiff=2;
812 else
813 *newdiff=1;
816 newdiff=(UBYTE *)newdiffl;
823 void mergediffs(UBYTE *diff, UWORD length, UBYTE *dest, UWORD offsets[], UBYTE lengths[], UBYTE data[]) {
824 UWORD unitsdone=0;
825 WORD n;
827 byteoffset=offsets[n];
829 code=*diff++;
830 len=(code & 0x3F)+1;
832 if((unitsdone+len)<<2 > byteoffset) {
834 /* Current code contains part of data which needs to be modified. */
836 if((code & 0x40)==0) { /* Clear or Set */
840 else {
841 *dest++=code;
849 void adddiff(UBYTE *previouscode, UBYTE newcode, ) {
855 void mergediffs(UBYTE *diff, UWORD length, UBYTE *newdiff, UWORD newlength, UBYTE *dest) {
856 UWORD newunitsdone=0; /* Words/Longs already merged. */
857 UWORD unitsdone=0;
858 UWORD len;
859 UBYTE code;
861 /* Merges two diffs into a single diff. */
863 /* 0x00 -> clear, 0x40 -> unchanged, 0x80 -> set, 0xC0 -> copy */
866 code=*newdiff++;
867 len=(code & 0x3F)+1;
869 if((code & 0x40)==0) { /* Clear or Set */
870 *dest++=code;
871 newunitsdone+=len;
873 else if((code & 0x80)!=0) { /* Copy */
874 ULONG *newdiffl;
875 ULONG *destl;
877 *dest++=code;
878 newunitsdone+=len;
880 destl=(ULONG *)dest;
881 newdiffl=(ULONG *)newdiff;
883 while(len--!=0) {
884 *destl++=*newdiffl++;
887 dest=(UBYTE *)destl;
888 newdiff=(UBYTE *)newdiffl;
890 else { /* Unchanged */
892 /* In this case the new diff contains a block of unchanged data.
893 This means we need to check the old diff to see what needs to
894 be done there. */
896 code2=*diff++;
897 len2=(code2 & 0x3F)+1;
899 if(unitsdone+len2 > newunitsdone) {
900 UWORD offset,size;
902 /* Current code in old diff is overlapping the unchanged area. */
904 offset=newunitsdone-unitsdone;
905 size=unitsdone+len2 - newunitsdone;
906 if(size>len) { /* Check if overlapping area is smaller */
907 size=len;
910 /* Calculated size and offset of overlapping area. */
914 else {
915 if((code2 & 0xC0)==0xC0) { /* Copy */
916 /* Skips any data for copy. */
917 diff+=len2<<2;
919 unitsdone+=len2;
940 Transactions
941 ------------
943 Operations are currently a diff of the original and the new
944 block. Creating this diff takes a lot of time and can
945 reduce performance considerably.
947 It should be possible to merge 2 diffs quickly without
948 having to creating an entirely new diff. This can be
949 accomplished by creating a function which takes 2 diffs and
950 merges them into one, letting the newer diff take
951 precedence.
953 Another function which would be needed is a function which
954 can create a diff based on the information to be changed
955 only. Old code which changes just a single piece of
956 information in a CacheBuffer looks like this:
959 preparecachebuffer(cb);
961 o->object.file.size=x;
963 errorcode=storecachebuffer(cb);
966 Instead it could be much faster if written like this:
969 changecachebuffer(cb, &o->object.file.size, x);
985 /* Format:
987 1 byte offset, 1 byte length. In LONGS.
991 void uncompress(ULONG *dest, UBYTE *data, UWORD length) {
992 ULONG *datal;
993 ULONG *d;
994 WORD l;
995 UBYTE *dataend=data+length;
997 if(*data++==1) {
998 l=bytes_block>>4;
999 d=dest;
1001 while(l-->0) {
1002 *d++=0;
1003 *d++=0;
1004 *d++=0;
1005 *d++=0;
1009 while(data<dataend) {
1010 d=dest + *data++;
1011 l=*data++;
1013 datal=(ULONG *)data;
1015 while(l-->0) {
1016 *d++=*datal++;
1019 data=(UBYTE *)datal;
1025 UWORD compress(ULONG *org, ULONG *new, UBYTE *dest) {
1026 ULONG *destl;
1027 UWORD longs_block=bytes_block>>2;
1028 UWORD longsleft=longs_block;
1029 UBYTE count;
1030 UBYTE *deststart=dest;
1032 *dest++=0;
1034 for(;;) {
1035 while(*org==*new) {
1036 org++;
1037 new++;
1038 if(--longsleft==0) {
1039 return(dest-deststart);
1043 *dest++=longs_block-longsleft;
1044 destl=(ULONG *)(dest+2);
1045 count=0;
1047 do {
1048 count++;
1049 org++;
1050 *destl++=*new++;
1051 if(--longsleft==0) {
1052 *dest=count;
1053 dest=(UBYTE *)destl;
1054 return(dest-deststart);
1056 } while(*org!=*new);
1058 *dest=count;
1059 dest=(UBYTE *)destl;
1065 UWORD compressfromzero(ULONG *new, UBYTE *dest) {
1066 ULONG *destl;
1067 UWORD longs_block=bytes_block>>2;
1068 UWORD longsleft=longs_block;
1069 UBYTE count;
1070 UBYTE *deststart=dest;
1072 *dest++=1;
1074 for(;;) {
1075 while(*new==0) {
1076 new++;
1077 if(--longsleft==0) {
1078 return(dest-deststart);
1082 *dest++=longs_block-longsleft;
1083 destl=(ULONG *)(dest+2);
1084 count=0;
1086 do {
1087 count++;
1088 *destl++=*new++;
1089 if(--longsleft==0) {
1090 *dest=count;
1091 dest=(UBYTE *)destl;
1092 return(dest-deststart);
1094 } while(*new!=0);
1096 *dest=count;
1097 dest=(UBYTE *)destl;
1101 #endif
1107 #ifdef BLOCKCOMPRESSION
1112 Diff compression scheme.
1114 Depending on the block size there will be a special
1115 header block which contains 2 bits for every 32 bytes
1116 the block consists of. We'll assume blocks of 512
1117 bytes for now.
1120 UWORD makediff(ULONG *new, ULONG *org, ULONG **io_diff) {
1121 ULONG *diff=*io_diff;
1122 ULONG data;
1123 UWORD mode=0;
1124 WORD n;
1126 for(n=0; n<8; n++) {
1127 mode<<=2;
1128 data=*new++;
1130 if(data==0) {
1131 mode|=2;
1133 else if(data==0xFFFFFFFF) {
1134 mode|=3;
1136 else if(data!=*org) {
1137 mode|=1;
1138 *diff++=data;
1141 org++;
1144 *io_diff=diff;
1146 return(mode);
1151 UWORD makedifffromzero(ULONG *new, ULONG **io_diff) {
1152 ULONG *diff=*io_diff;
1153 ULONG data;
1154 UWORD mode=0;
1155 WORD n;
1157 for(n=0; n<8; n++) {
1158 mode<<=2;
1159 data=*new++;
1161 if(data==0) {
1162 mode|=2;
1164 else if(data==0xFFFFFFFF) {
1165 mode|=3;
1167 else {
1168 mode|=1;
1169 *diff++=data;
1173 *io_diff=diff;
1175 return(mode);
1178 #if 0
1180 if(newfilesize!=gh->size) {
1181 struct CacheBuffer *cb;
1182 struct fsObject *o;
1184 if((errorcode=readobject(lock->objectnode,&cb,&o))==0) {
1185 UBYTE modifiedblocks[4]={0,0,0,255};
1187 preparecachebuffer(cb);
1189 checksum_writelong(cb->data, &o->object.file.size, newfilesize);
1191 gh->size=newfilesize;
1193 modifiedblocks[1]=(&o->object.file.size - cb->data)>>5;
1194 modifiedblocks[2]=(&o->object.file.size - cb->data+3)>>5;
1196 errorcode=changecachebuffer(cb, modifiedblocks)
1200 void checksum_writelong(struct fsBlockHeader *bh, void *dest, ULONG data) {
1201 ULONG original;
1202 /* Only handles longs written to even addresses! */
1203 original=*((ULONG *)dest);
1204 *((ULONG *)dest)=data;
1206 if(( ((UBYTE *)bh - (UBYTE *)dest) & 0x03)!=0) {
1207 /* Word aligned address. */
1209 original=(original<<16)|(original>>16);
1210 data=(data<<16)|(data>>16);
1212 bh->checksum=~(~bh->checksum - original + data);
1215 #endif
1220 UWORD mergediffs(UBYTE *olddiff, UBYTE *newdiff, UWORD length, ULONG *new, ULONG *org, UBYTE *modifiedblocks) {
1221 ULONG *header=(ULONG *)newdiff;
1222 ULONG mc,newmc=0;
1223 UWORD *modesstart=(UWORD *)(newdiff+bytes_block+(bytes_block>>4));
1224 UWORD *modes=(UWORD *)(newdiff+bytes_block+(bytes_block>>4));
1225 UWORD *oldmodes=(UWORD *)(olddiff+length);
1226 UWORD *newdiffw;
1227 WORD b;
1229 mc=*((ULONG *)olddiff);
1230 olddiff+=4;
1232 for(b=0; b<16; b++) {
1233 newmc<<=2;
1235 if(b==*modifiedblocks) {
1236 UWORD mode;
1238 while(*++modifiedblocks==b) {
1241 if(org==0) {
1242 mode=makedifffromzero(new, (ULONG **)&newdiff);
1244 else {
1245 mode=makediff(new, org, (ULONG **)&newdiff);
1248 if(mode==0x5555) { // All copied.
1249 newmc|=1;
1251 else if(mode==0xAAAA) { // All cleared.
1252 newmc|=2;
1254 else if(mode!=0) {
1255 newmc|=3;
1256 *--modes=mode;
1259 else {
1260 switch(mc & 0xC0000000) {
1261 case 0x40000000:
1263 ULONG *newdiffl=(ULONG *)newdiff;
1264 ULONG *olddiffl=(ULONG *)olddiff;
1265 WORD n=8;
1267 newmc|=1;
1269 while(n-->0) {
1270 *newdiffl++=*olddiffl++;
1273 newdiff=(UBYTE *)newdiffl;
1274 olddiff=(UBYTE *)olddiffl;
1276 break;
1277 case 0x80000000:
1278 newmc|=2;
1279 break;
1280 case 0xC0000000:
1282 ULONG *newdiffl=(ULONG *)newdiff;
1283 ULONG *olddiffl=(ULONG *)olddiff;
1284 UWORD mode;
1285 WORD n=8;
1287 newmc|=3;
1289 mode=*--oldmodes;
1290 *--modes=mode;
1292 while(n-->0) {
1293 if((mode & 0xC000)==0x4000) {
1294 *newdiffl++=*olddiffl++;
1296 mode<<=2;
1299 newdiff=(UBYTE *)newdiffl;
1300 olddiff=(UBYTE *)olddiffl;
1305 new+=8;
1306 org+=8;
1309 *header=newmc;
1311 newdiffw=(UWORD *)newdiff;
1313 while(modes!=modesstart) {
1314 *newdiffw++=*modes++;
1317 return((UWORD)((UBYTE *)newdiffw-(UBYTE *)header));
1321 void uncompress(ULONG *dest, UBYTE *diff, UWORD length) {
1322 ULONG mc;
1323 UWORD *modes=(UWORD *)(diff+length);
1324 WORD b=16;
1326 mc=*((ULONG *)diff);
1327 diff+=4;
1329 while(b-->0) {
1330 switch(mc & 0xC0000000) {
1331 case 0x00000000:
1332 dest+=8;
1333 break;
1334 case 0x40000000:
1336 ULONG *diffl=(ULONG *)diff;
1337 WORD n=8;
1339 while(n-->0) {
1340 *dest++=*diffl++;
1343 diff=(UBYTE *)diffl;
1345 break;
1346 case 0x80000000:
1348 WORD n=8;
1350 while(n-->0) {
1351 *dest++=0;
1354 break;
1355 default:
1357 ULONG *diffl=(ULONG *)diff;
1358 UWORD mode=*--modes;
1359 WORD n=8;
1361 while(n-->0) {
1362 switch(mode & 0xC000) {
1363 case 0x0000:
1364 dest++;
1365 break;
1366 case 0x4000:
1367 *dest++=*diffl++;
1368 break;
1369 case 0x8000:
1370 *dest++=0x00000000;
1371 break;
1372 default:
1373 *dest++=0xFFFFFFFF;
1376 mode<<=2;
1379 diff=(UBYTE *)diffl;
1383 mc<<=2;
1389 /* Blocks will be processed 32 bytes at the time.
1391 Master Control block:
1393 %00 = unchanged, no control word.
1394 %01 = 32 bytes of data, no control word.
1395 %10 = cleared (compress from zero!).
1396 %11 = use control word.
1398 Control WORD:
1400 %00 = unchanged (0x0000)
1401 %01 = use 32-bit value (0x5555)
1402 %10 = cleared (0xAAAA)
1403 %11 = set (0xFFFF) */
1407 UWORD compress(ULONG *new, ULONG *org, UBYTE *diff) {
1408 ULONG *header=(ULONG *)diff;
1409 ULONG mc=0;
1410 UWORD *modesstart=(UWORD *)(diff+bytes_block+(bytes_block>>4));
1411 UWORD *modes=(UWORD *)(diff+bytes_block+(bytes_block>>4));
1412 UWORD *diffw;
1413 UWORD mode;
1414 WORD b=16;
1416 diff+=4;
1418 while(b-->0) {
1419 mc<<=2;
1421 mode=makediff(new, org, (ULONG **)&diff);
1423 if(mode==0x5555) {
1424 mc|=1;
1426 else if(mode==0xAAAA) {
1427 mc|=2;
1429 else if(mode!=0) {
1430 mc|=3;
1431 *--modes=mode;
1434 new+=8;
1435 org+=8;
1438 *header=mc;
1440 diffw=(UWORD *)diff;
1442 while(modes!=modesstart) {
1443 *diffw++=*modes++;
1446 return((UWORD)((UBYTE *)diffw-(UBYTE *)header));
1451 UWORD compressfromzero(ULONG *new, UBYTE *diff) {
1452 ULONG *header=(ULONG *)diff;
1453 ULONG mc=0;
1454 UWORD *modesstart=(UWORD *)(diff+bytes_block+(bytes_block>>4));
1455 UWORD *modes=(UWORD *)(diff+bytes_block+(bytes_block>>4));
1456 UWORD *diffw;
1457 UWORD mode;
1458 WORD b=16;
1460 diff+=4;
1462 while(b-->0) {
1463 mc<<=2;
1465 mode=makedifffromzero(new, (ULONG **)&diff);
1467 if(mode==0x5555) {
1468 mc|=1;
1470 else if(mode==0xAAAA) {
1471 mc|=2;
1473 else {
1474 mc|=3;
1475 *--modes=mode;
1478 new+=8;
1481 *header=mc;
1483 diffw=(UWORD *)diff;
1485 while(modes!=modesstart) {
1486 *diffw++=*modes++;
1489 return((UWORD)((UBYTE *)diffw-(UBYTE *)header));
1494 #endif
1499 void checksum_writelong_be(struct fsBlockHeader *bh, void *dest, ULONG data) {
1500 ULONG original;
1502 /* Only handles longs written to even addresses! */
1504 original=BE2L(*((ULONG *)dest));
1505 *((ULONG *)dest)=L2BE(data);
1507 if(( ((UBYTE *)bh - (UBYTE *)dest) & 0x03)!=0) {
1509 /* Word aligned address. */
1511 original=(original<<16)|(original>>16);
1512 data=(data<<16)|(data>>16);
1515 bh->be_checksum=~L2BE((~BE2L(bh->be_checksum) - original + data));
1518 void checksum_writelong(struct fsBlockHeader *bh, void *dest, ULONG data) {
1519 #if 0
1520 ULONG original;
1522 /* Only handles longs written to even addresses! */
1524 original=*((ULONG *)dest);
1525 *((ULONG *)dest)=data;
1527 if(( ((UBYTE *)bh - (UBYTE *)dest) & 0x03)!=0) {
1529 /* Word aligned address. */
1531 original=(original<<16)|(original>>16);
1532 data=(data<<16)|(data>>16);
1535 bh->be_checksum=~(~bh->be_checksum - original + data);
1536 #else
1537 checksum_writelong_be(bh, dest, data);
1538 #endif