2 Copyright (c) 2007 David Swasey; see COPYRIGHT.
4 Hfsreaddir skips entries whose names contain NUL.
5 Hfsbadblock is untested.
18 static char Rprefix[] = "._";
19 enum { Rplen = nelem(Rprefix)-1 };
21 static int hfssync(Fsys*);
22 static int hfswrapper(Fsys*);
23 static int hfstreesync(Hfs*, Fork*, Tree*, int);
24 static u32int hfsmetadir(Hfs*);
25 static void hfsclose(Fsys*);
26 static Block* hfsblockread(Fsys*, u64int);
28 static Nfs3Status hfsroot(Fsys*, Nfs3Handle*);
29 static Nfs3Status hfsgetattr(Fsys*, SunAuthUnix*, Nfs3Handle*, Nfs3Attr*);
30 static Nfs3Status hfsaccess(Fsys *fsys, SunAuthUnix*, Nfs3Handle *, u32int, u32int*, Nfs3Attr *attr);
31 static Nfs3Status hfslookup(Fsys*, SunAuthUnix*, Nfs3Handle*, char*, Nfs3Handle*);
32 static Nfs3Status _hfslookup(Hfs*, u32int, char*, Treeref*);
33 static Nfs3Status hfsreaddir(Fsys *fsys, SunAuthUnix*, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*);
34 static Nfs3Status hfsreadfile(Fsys*, SunAuthUnix*, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*);
35 static Nfs3Status hfsreadlink(Fsys*, SunAuthUnix*, Nfs3Handle*, char**);
37 static int hfsextentsearch(Hfs*, u32int, int, u32int, u32int*, Extent*);
38 static int hfscatsearch(Hfs*, Catalogkey*, Treeref*);
39 static int _hfscatalogkeycmp(uchar*, int, int*, Key*, int);
40 static int hfstreesearch(Tree*, Key*, int*, Treeref*);
41 static void hfsref(Tree*, Treeref*);
42 static void hfsrefput(Treeref*);
43 static int hfsrefnode(Treeref*, u32int);
44 static int hfsrefrec(Treeref*, int);
45 static int hfsrefnextrec(Treeref*);
47 static int hfsforkread(Hfs*, Fork*, uchar*, u32int, u64int);
48 static Block* hfsforkblock(Hfs*, Fork*, u32int);
49 static Block* hfsblock(Hfs*, u32int);
51 static void getnodedesc(Node*, uchar*);
52 static void getfork(Fork*, u32int, int, uchar*);
53 static void getextents(Extent*, uchar*);
54 static void getextent(Extent*, uchar*);
55 static int getextentkey(Extentkey*, uchar*, int);
56 static int getcatalogrecord(Inode*, uchar*, int);
57 static int getcatalogthread(Catalogkey*, uchar*, int);
58 static int getcatalogkey(Catalogkey*, uchar*, int, int);
59 static int getname(Name*, uchar*);
60 static u32int gettime(uchar*);
61 static u64int get64(uchar*);
62 static u32int get32(uchar*);
63 static int get16(uchar*);
64 static void put32(uchar*, u32int);
66 static int hfsinamecmp(Name*, Name*);
67 static int hfsnamecmp(Name*, Name*);
70 fsysopenhfs(Disk *disk)
75 fsys = emalloc(sizeof(Fsys));
76 fs = emalloc(sizeof(Hfs));
81 fsys->_readblock = hfsblockread;
82 fsys->_sync = hfssync;
83 fsys->_root = hfsroot;
84 fsys->_getattr = hfsgetattr;
85 fsys->_access = hfsaccess;
86 fsys->_lookup = hfslookup;
87 fsys->_readfile = hfsreadfile;
88 fsys->_readlink = hfsreadlink;
89 fsys->_readdir = hfsreaddir;
90 fsys->_close = hfsclose;
93 if(hfswrapper(fsys) < 0 || hfssync(fsys) < 0)
110 * We're not supposed to close the disk passed to
111 * hfsopen, but if we created our own partition disk
112 * we need to close that. It will close its subdisk
113 * unless we call diskpartabandon. Bad planning.
115 if(fs->disk && fs->disk != fsys->disk){
116 diskpartabandon(fs->disk);
124 hfswrapper(Fsys *fsys)
130 int magic, hfsstart, subsig, substart, subnblocks;
136 if((b = diskread(disk, 162, 1024)) == nil)
140 hfsblocksize = get32(mdb+20);
141 hfsstart = get16(mdb+28);
142 subsig = get16(mdb+124);
143 substart = get16(mdb+126);
144 subnblocks = get16(mdb+128);
149 if(subsig != Hfsplussig && subsig != Hfsxsig)
152 offset = hfsstart*512 + substart*hfsblocksize;
153 size = subnblocks*hfsblocksize;
155 if((fs->disk = diskpart(disk, offset, size)) == nil)
157 if(debug) fprint(2, "wrapped hfs size 0x%ullx offset 0x%ullx\n", size, offset);
162 checkvolhdr(uchar *vh)
173 werrstr("bad volume header magic 0x%ux", magic);
190 if((b = diskread(disk, 512, 1024)) == nil)
193 if((sensitive = checkvolhdr(vh)) < 0)
195 fs->blocksize = get32(vh+40);
196 fs->nblock = get32(vh+44);
197 fs->nfree = get32(vh+48);
198 fs->hasbadblocks = get32(vh+4) & (1<<9);
199 getfork(&fs->alloc, AllocId, Dfork, vh+112);
200 getfork(&fs->extentsfork, ExtentsId, Dfork, vh+192);
201 getfork(&fs->catalogfork, CatalogId, Dfork, vh+272);
205 if(hfstreesync(fs, &fs->extentsfork, &fs->extents, 0) < 0)
207 if(hfstreesync(fs, &fs->catalogfork, &fs->catalog, sensitive) < 0)
209 fs->hlinkparent = hfsmetadir(fs);
211 fsys->blocksize = fs->blocksize;
212 fsys->nblock = fs->nblock;
213 if(debug) fprint(2, "hfs %ud %ud-byte blocks (%ud free, %s bad)\n",
214 fs->nblock, fs->blocksize, fs->nfree, fs->hasbadblocks?"some":"none");
223 hfstreesync(Hfs *fs, Fork *fork, Tree *tree, int sensitive)
230 if(fork->extent[0].count == 0){
231 if(debug) fprint(2, "tree fork empty\n");
234 if((b = hfsblock(fs,fork->extent[0].start)) == nil)
236 getnodedesc(&node, b->data);
237 if(node.type != HeaderNode){
238 if(debug) fprint(2, "bad header node type %d\n", node.type);
242 tree->nodesize = get16(hr+18);
243 tree->nnodes = get32(hr+22);
244 tree->root = get32(hr+2);
245 tree->height = get16(hr);
246 tree->maxkeylen = get16(hr+20);
247 tree->indexkeylen = (get32(hr+38)&4) ? 0 : tree->maxkeylen;
248 tree->sensitive = sensitive && hr[37]==0xBC;
252 if(debug) fprint(2, "tree %ud %ud %d-byte nodes\n",
253 fork->cnid, tree->nnodes, tree->nodesize);
257 werrstr("bad tree %ud header", fork->cnid);
265 static Rune name[] = {0,0,0,0,'H','F','S','+',' ','P','r','i','v','a','t','e',' ','D','a','t','a'};
271 key.u.name.len = nelem(name);
272 memcpy(key.u.name.name, name, sizeof name);
273 if(hfscatsearch(fs, &key, &ref) < 0)
275 if(getcatalogrecord(&ino, ref.data, ref.dlen) < 0)
277 if((ino.mode&IFMT) != IFDIR)
280 if(debug) fprint(2, "metadata directory %ud\n", ino.cnid);
284 if(debug) fprint(2, "metadata directory not found\n");
290 hfsbadblock(Hfs *fs, u32int bno)
295 if(hfsextentsearch(fs, BadblockId, Dfork, bno, nil, e) < 0)
298 Don't lightly throw away a block.
300 for(i=0; i<NEXTENTS; i++)
301 if(e[i].start <= bno && bno < e[i].start+e[i].count)
303 if(debug) fprint(2, "corrupt badblock record, block %ud\n", bno);
308 hfsblockread(Fsys *fsys, u64int vbno)
316 if(vbno >= fs->nblock){
317 if(debug) fprint(2, "block %llud past end of volume\n", vbno);
323 if((b = hfsforkblock(fs, &fs->alloc, n/fs->blocksize)) == nil){
324 if(debug) fprint(2, "can't read alloc bitmap for block %ud\n", bno);
325 /* assume it's used */
328 alloc = b->data[n%fs->blocksize] & (1<<(7-(bno&7)));
334 if(fs->hasbadblocks && hfsbadblock(fs, bno)){
335 if(debug) fprint(2, "bad block %ud\n", bno);
339 b = hfsblock(fs, bno);
340 if(debug && b == nil) fprint(2, "can't read block %ud\n", bno);
345 hasresource(Inode *ino)
347 return (ino->mode&IFMT)==IFREG && ino->u.f.rfork.size>0;
351 useresource(Inode *ino)
353 ino->fileid = ((u64int)1)<<32 | ino->cnid;
354 ino->u.f.nhdr = Adlen;
355 ino->u.f.fork = &ino->u.f.rfork;
359 ref2ino(Hfs *fs, Treeref *ref, Inode *ino)
361 static uchar magic[] = {'h','l','n','k','h','f','s','+'};
366 if(getcatalogrecord(ino, ref->data, ref->dlen) < 0)
369 if((ino->mode&IFMT) == IFREG
370 && memcmp(ino->u.f.info, magic, nelem(magic)) == 0){
371 if(debug) print("iNode%ud...", ino->special);
372 if(fs->hlinkparent == 0)
374 key.parent = fs->hlinkparent;
375 key.u.name.len = runesnprint(key.u.name.name, sizeof key.u.name.name,
376 "iNode%ud", ino->special);
377 if(hfscatsearch(fs, &key, &hlink) < 0)
380 if(getcatalogrecord(ino, hlink.data, hlink.dlen) < 0)
385 ino->nlink = ino->special;
395 mkhandle(Nfs3Handle *h, int rsrc, u32int cnid)
403 hfsroot(Fsys *fsys, Nfs3Handle *h)
406 mkhandle(h, 0, RootId);
411 handle2ino(Hfs *fs, Nfs3Handle *h, Treeref *ref, Catalogkey *key, Inode *ino)
419 return Nfs3ErrBadHandle;
421 cnid = get32(h->h+1);
422 if(debug) print("cnid %ud%s...", cnid, rsrc ? " rsrc" : "");
429 /* map cnid to full catalog key */
432 if(hfscatsearch(fs, key, ref) < 0)
434 if(getcatalogthread(key, ref->data, ref->dlen) < 0)
438 if(debug) print("{%ud,%.*S}...", key->parent, key->u.name.len, key->u.name.name);
440 /* map full key to catalog info */
441 if(hfscatsearch(fs, key, ref) < 0)
444 if(ref2ino(fs, ref, ino) < 0)
447 if(!hasresource(ino)){
449 return Nfs3ErrBadHandle;
465 ino2attr(Hfs *fs, Inode *ino, Nfs3Attr *attr)
469 switch(ino->mode&IFMT){
471 attr->type = Nfs3FileFifo;
474 attr->type = Nfs3FileChar;
477 attr->type = Nfs3FileDir;
480 attr->type = Nfs3FileBlock;
483 attr->type = Nfs3FileReg;
486 attr->type = Nfs3FileSymlink;
489 attr->type = Nfs3FileSocket;
493 if(debug) fprint(2, "bad format %uo\n", ino->mode&IFMT);
494 return Nfs3ErrBadHandle;
497 attr->mode = ino->mode&07777;
498 attr->nlink = ino->nlink;
499 attr->uid = ino->uid;
500 attr->gid = ino->gid;
501 if(attr->type==Nfs3FileReg || attr->type==Nfs3FileSymlink){
502 attr->size = ino->u.f.nhdr+ino->u.f.fork->size;
503 attr->used = (u64int)ino->u.f.fork->nblocks*fs->blocksize;
509 if(attr->type==Nfs3FileBlock || attr->type==Nfs3FileChar){
511 attr->major = (rdev>>8)&0xFF; /* not mentioned in the tech note */
512 attr->minor = rdev & 0xFFFF00FF;
518 attr->fileid = ino->fileid;
519 attr->atime.sec = ino->atime;
520 attr->atime.nsec = 0;
521 attr->mtime.sec = ino->mtime;
522 attr->mtime.nsec = 0;
523 attr->ctime.sec = ino->ctime;
524 attr->ctime.nsec = 0;
529 ingroup(SunAuthUnix *au, uint gid)
533 for(i=0; i<au->ng; i++)
540 inoperm(Inode *ino, SunAuthUnix *au, int need)
547 have = ino->mode&0777;
548 if(ino->uid == au->uid)
550 else if(ino->gid == au->gid || ingroup(au, ino->gid))
553 if((have&need) != need)
554 return Nfs3ErrNotOwner; /* really EPERM */
559 hfsgetattr(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, Nfs3Attr *attr)
566 if((ok = handle2ino(fs, h, nil, nil, &ino)) != Nfs3Ok)
569 USED(au); /* anyone can getattr */
570 return ino2attr(fs, &ino, attr);
574 hfsaccess(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int want, u32int *got, Nfs3Attr *attr)
582 if((ok = handle2ino(fs, h, nil, nil, &ino)) != Nfs3Ok)
585 have = ino.mode&0777;
586 if(ino.uid == au->uid)
588 else if(ino.gid == au->gid || ingroup(au, ino.gid))
592 if((want&Nfs3AccessRead) && (have&AREAD))
593 *got |= Nfs3AccessRead;
594 if((want&Nfs3AccessLookup) && (ino.mode&IFMT)==IFDIR && (have&AEXEC))
595 *got |= Nfs3AccessLookup;
596 if((want&Nfs3AccessExecute) && (ino.mode&IFMT)!=IFDIR && (have&AEXEC))
597 *got |= Nfs3AccessExecute;
599 return ino2attr(fs, &ino, attr);
603 utf2name(Name *n, char *name)
612 return Nfs3ErrNameTooLong;
613 name += chartorune(p, name);
615 *p = '/'; /* not mentioned in the tech note */
624 name2utf(char *buf, Name *name)
629 for(i=0; i<name->len; i++){
630 if(name->name[i] == '/'){ /* not mentioned in the tech note */
635 len += runetochar(buf+len, name->name+i);
641 hfslookup(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char *name, Nfs3Handle *nh)
651 if((ok = handle2ino(fs, h, nil, &key, &ino)) != Nfs3Ok)
654 if((ino.mode&IFMT) != IFDIR)
655 return Nfs3ErrNotDir;
657 if((ok = inoperm(&ino, au, AEXEC)) != Nfs3Ok)
660 if(strcmp(name, ".") == 0){
661 mkhandle(nh, 0, ino.cnid);
664 if(strcmp(name, "..") == 0){
665 mkhandle(nh, 0, key.parent);
670 if((ok = _hfslookup(fs, ino.cnid, name, &ref)) != Nfs3Ok){
671 if(memcmp(name, Rprefix, Rplen)==0
672 && _hfslookup(fs, ino.cnid, name+Rplen, &ref)==Nfs3Ok)
677 if(ref2ino(fs, &ref, &target) < 0)
680 if(rsrc && !hasresource(&target))
682 mkhandle(nh, rsrc, target.cnid);
691 _hfslookup(Hfs *fs, u32int parent, char *name, Treeref *ref)
697 if((ok = utf2name(&key.u.name, name)) != Nfs3Ok)
699 if(hfscatsearch(fs, &key, ref) < 0)
706 For the moment, hfsreaddir does not return entries whose names
707 contain NUL, avoiding errors like "ls: : No such file or
708 directory" when listing a mounted root.
715 for(i=0; i<n->len; i++)
722 hfsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
723 u64int cookie, uchar **pdata, u32int *pcount, u1int *peof)
731 char name[Rplen+UTFNAMELEN];
732 uchar *dp, *dep, *ndp, *data;
739 if((ok = handle2ino(fs, h, nil, nil, &ino)) != Nfs3Ok)
742 if((ino.mode&IFMT) != IFDIR)
743 return Nfs3ErrNotDir;
745 if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
748 if(ino.u.nentries>>31)
750 nentries = ino.u.nentries*2; /* even data, odd resource */
753 cnid = cookie&0xFFFFFFFF;
754 if(debug) print("readdir %ud %ud %ud...", cnid, i, nentries);
762 dp = mallocz(count, 1);
769 The catalog order relation ensures that records for a
770 dir's children are contiguous and preceded by its
774 key.parent = ino.cnid;
776 if(hfscatsearch(fs, &key, &ref) < 0)
780 mkhandle(&ch, i&1, cnid);
781 if((ok = handle2ino(fs, &ch, &ref, &key, &child)) != Nfs3Ok)
783 if(key.parent != ino.cnid)
788 memset(&e, 0, sizeof e);
789 for(; i<nentries; i++){
792 if(hfsrefnextrec(&ref) < 0)
794 if(getcatalogkey(&key, ref.key, ref.klen, 1) < 0)
796 if(key.parent != ino.cnid)
798 if(ref2ino(fs, &ref, &child) < 0)
801 else if(!hasresource(&child))
805 if(hfshidename(&key.u.name))
807 e.fileid = child.fileid;
810 memcpy(name, Rprefix, Rplen);
811 e.namelen = Rplen+name2utf(name+Rplen, &key.u.name);
814 e.namelen = name2utf(name, &key.u.name);
815 e.cookie = ((u64int)i)<<32 | child.cnid;
816 e.haveAttr = (ino2attr(fs, &child, &e.attr) == Nfs3Ok);
818 mkhandle(&e.handle, rsrc, child.cnid);
819 if(debug) print("%s/0x%llux ", e.name, e.fileid);
820 if(nfs3entrypack(dp, dep, &ndp, &e) < 0)
832 if(debug) fprint(2, "%.*S: bad parent %ud != %ud\n",
833 key.u.name.len, key.u.name.name, key.parent, ino.cnid);
841 appledouble(Inode *ino, uchar *ad)
843 static uchar Adhdr[Adlen-4-Filen] =
845 0,5,22,7,0,2,0,0, /* magic */
846 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* filler */
848 0,0,0,9, /* magic: finder info */
849 0,0,0,Fioff, /* offset */
850 0,0,0,Filen, /* length */
851 0,0,0,2, /* magic: rfork */
852 0,0,0,Adlen, /* offset */
855 if(ino->u.f.rfork.size>>32){
856 if(debug) fprint(2, "resource fork %ud too large\n", ino->cnid);
859 memcpy(ad, Adhdr, nelem(Adhdr));
860 put32(ad+nelem(Adhdr), ino->u.f.rfork.size);
861 memcpy(ad+Fioff, ino->u.f.info, Filen);
866 hfsreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
867 u64int offset, uchar **pdata, u32int *pcount, u1int *peof)
871 uchar *data, prefix[Adlen];
877 if((ok = handle2ino(fs, h, nil, nil, &ino)) != Nfs3Ok)
880 if((ino.mode&IFMT) != IFREG)
883 if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
886 size = ino.u.f.nhdr+ino.u.f.fork->size;
893 if(offset+count > size)
895 data = mallocz(count, 1);
898 if(offset < ino.u.f.nhdr){
899 if(appledouble(&ino, prefix) < 0)
904 memcpy(data, prefix+offset, skip);
908 offset -= ino.u.f.nhdr;
911 if(hfsforkread(fs, ino.u.f.fork, data+skip, count-skip, offset) < 0)
914 *peof = (offset+count == size);
925 hfsreadlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char **link)
934 if((ok = handle2ino(fs, h, nil, nil, &ino)) != Nfs3Ok)
937 if((ino.mode&IFMT) != IFLNK)
940 if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
943 len = ino.u.f.dfork.size;
944 if(len > 10240) /* arbitrary limit */
947 data = mallocz(len+1, 1);
950 if(hfsforkread(fs, &ino.u.f.dfork, data, len, 0) < 0){
960 hfsextentkeycmp(uchar *buf, int len, int *order, Key *key)
965 if(getextentkey(&a, buf, len) < 0)
969 diff = a.cnid - b->cnid;
971 diff = a.type - b->type;
973 diff = a.bno - b->bno;
980 hfsextentsearch(Hfs *fs, u32int cnid, int type, u32int bno, u32int *startblock, Extent *e)
986 key._cmp = hfsextentkeycmp;
991 if(hfstreesearch(&fs->extents, &key, nil, &ref) < 0)
993 if(ref.dlen != NEXTENTS*Extentlen){
994 if(debug) fprint(2, "extents for fork %ud %d block %ud malformed (%d bytes)\n",
995 cnid, type, bno, ref.dlen);
998 getextentkey(&k, ref.key, ref.klen);
999 if(k.cnid != cnid || k.type != type)
1002 *startblock = k.bno;
1003 getextents(e, ref.data);
1013 hfscatalogkeycmp(uchar *buf, int len, int *order, Key *key)
1015 return _hfscatalogkeycmp(buf, len, order, key, 1);
1019 hfscatalogikeycmp(uchar *buf, int len, int *order, Key *key)
1021 return _hfscatalogkeycmp(buf, len, order, key, 0);
1025 hfscatsearch(Hfs *fs, Catalogkey *k, Treeref *ref)
1030 key._cmp = fs->catalog.sensitive ? hfscatalogkeycmp : hfscatalogikeycmp;
1032 if(hfstreesearch(&fs->catalog, &key, &order, ref) < 0 || order != 0){
1040 _hfscatalogkeycmp(uchar *buf, int len, int *order, Key *key, int sensitive)
1045 if(getcatalogkey(&a, buf, len, 0) < 0)
1049 diff = a.parent - b->parent;
1051 if(getname(&a.u.name, a.u.b) < 0)
1054 diff = hfsnamecmp(&a.u.name, &b->u.name);
1056 diff = hfsinamecmp(&a.u.name, &b->u.name);
1063 hfskeycmp(uchar *k, int len, int *order, Key *key)
1065 return (*key->_cmp)(k, len, order, key);
1069 Find the record with the largest key k' <= key.
1072 hfstreesearch(Tree *tree, Key *key, int *porder, Treeref *ref)
1075 int h, i, found, order, rel;
1079 rel = 0; /* silence a warning */
1080 for(h=tree->height; h>0; h--){
1081 if(hfsrefnode(ref, nno) < 0)
1085 We could use binary search.
1087 for(i=0; i < ref->node.nrec; i++){
1088 if(hfsrefrec(ref, i) < 0)
1090 if(hfskeycmp(ref->key, ref->klen, &order, key) < 0)
1099 if(found < 0 || hfsrefrec(ref, found) < 0)
1107 if(debug) fprint(2, "tree %ud node %ud rec %d bad %d-byte pointer\n",
1108 ref->cnid, ref->nno, ref->rno, ref->dlen);
1111 nno = get32(ref->data);
1120 hfstreenodeclose(Block *b)
1126 hfstreenode(Tree *tree, u32int nno)
1135 len = tree->nodesize;
1136 if(nno >= tree->nnodes){
1137 if(debug) fprint(2, "bad tree %ud node %ud\n", tree->fork->cnid, nno);
1141 if(len == fs->blocksize)
1142 return hfsforkblock(fs, fork, nno);
1144 b = mallocz(sizeof(Block)+len, 1);
1147 b->data = (uchar*)&b[1];
1149 if(hfsforkread(fs, fork, b->data, len, (u64int)nno*len) < 0){
1153 b->_close = hfstreenodeclose;
1161 if rno >= 0, then every field is valid.
1162 if block != nil, then tree through node are valid.
1163 tree and cnid are valid.
1166 hfsref(Tree *tree, Treeref *ref)
1168 memset(ref, 0, sizeof(Treeref));
1170 ref->cnid = ref->tree->fork->cnid;
1175 hfsrefput(Treeref *ref)
1177 blockput(ref->block);
1183 hfsrefnode(Treeref *ref, u32int nno)
1185 if(ref->block && ref->nno==nno)
1189 blockput(ref->block);
1190 if((ref->block = hfstreenode(ref->tree, nno)) == nil)
1193 getnodedesc(&ref->node, ref->block->data);
1195 Hfsrefrec assumes all record offsets lie in the block.
1197 if(ref->node.nrec > (ref->tree->nodesize-Ndlen-2)/2){
1198 if(debug) fprint(2, "tree %ud node %ud bad nrec %d\n",
1199 ref->cnid, ref->nno, ref->node.nrec);
1200 blockput(ref->block);
1208 hfsrefrec(Treeref *ref, int rno)
1210 uchar *node, *o, *r, *n;
1213 if(ref->block == nil || rno < 0 || rno >= ref->node.nrec)
1220 We could use Tree.indexkeylen to avoid reading offsets
1221 from extent tree nodes.
1223 node = ref->block->data;
1224 o = node+ref->tree->nodesize-2*(rno+1);
1226 n = node+get16(o-2);
1227 if(r < node+Ndlen || n <= r+2 || o < n){
1228 if(debug) fprint(2, "tree %ud node %ud rec %d bad offsets %d %d %d\n",
1229 ref->cnid, ref->nno, rno, r-node, n-node, o-node);
1233 klen = 2+get16(r); /* actual length */
1236 ref->data = r+klen+(klen&1);
1237 ref->dlen = n-ref->data; /* includes any pad byte */
1242 hfsrefnextrec(Treeref *ref)
1247 if(ref->block == nil)
1249 rno = ref->rno < 0 ? 0 : ref->rno+1;
1250 if(rno < ref->node.nrec)
1251 return hfsrefrec(ref, rno);
1252 nno = ref->node.next;
1253 if(nno==0 || hfsrefnode(ref, nno) < 0 || ref->node.nrec==0)
1255 return hfsrefrec(ref, 0);
1259 hfsforkread(Hfs *fs, Fork *fork, uchar *data, u32int count, u64int offset)
1265 if(offset+count > fork->size){
1266 if(debug) fprint(2, "read past end of fork\n");
1273 bno = offset/fs->blocksize;
1274 skip = offset%fs->blocksize;
1275 frag = fs->blocksize - skip;
1278 if((b = hfsforkblock(fs, fork, bno)) == nil)
1280 memmove(data, b->data+skip, frag);
1285 while(count > fs->blocksize){
1286 if((b = hfsforkblock(fs, fork, bno)) == nil)
1288 memmove(data, b->data, fs->blocksize);
1290 data += fs->blocksize;
1291 count -= fs->blocksize;
1295 if((b = hfsforkblock(fs, fork, bno)) == nil)
1297 memmove(data, b->data, count);
1304 hfsforkblock(Hfs *fs, Fork *fork, u32int bno)
1309 Extent other[NEXTENTS];
1311 if(bno >= fork->nblocks){
1312 if(debug) fprint(2, "bad fork %ud %d block %ud\n",
1313 fork->cnid, fork->type, bno);
1318 for(i=0; i<NEXTENTS; i++, e++){
1320 return hfsblock(fs, e->start+skip);
1324 if(fork->cnid == ExtentsId){
1325 if(debug) fprint(2, "extents fork overflow\n");
1328 if(hfsextentsearch(fs, fork->cnid, fork->type, bno, &start, other) < 0)
1332 for(i=0; i<NEXTENTS; i++, e++){
1334 return hfsblock(fs, e->start+skip);
1338 if(debug) fprint(2, "bad extents overflow fork %ud %d block %ud skip %ud\n",
1339 fork->cnid, fork->type, bno, skip);
1344 hfsblock(Hfs *fs, u32int bno)
1346 if(bno >= fs->nblock){
1347 if(debug) fprint(2, "bad block %ud\n", bno);
1350 return diskread(fs->disk, fs->blocksize, (u64int)bno*fs->blocksize);
1354 getnodedesc(Node *n, uchar *b)
1356 n->type = (s8int)b[8];
1358 n->nrec = get16(b+10);
1362 getfork(Fork *f, u32int cnid, int type, uchar *b)
1367 f->nblocks = get32(b+12);
1368 getextents(f->extent, b+16);
1372 getextents(Extent *e, uchar *b)
1376 for(i=0; i<NEXTENTS; i++){
1383 getextent(Extent *e, uchar *b)
1385 e->start = get32(b);
1386 e->count = get32(b+4);
1390 getextentkey(Extentkey *k, uchar *b, int len)
1393 if(debug) fprint(2, "bad extents key length %d\n", len);
1396 k->cnid = get32(b+4);
1398 k->bno = get32(b+8);
1403 getcatalogrecord(Inode *ino, uchar *b, int blen)
1408 if(blen != Folderlen && blen != Filelen){
1409 if(debug) fprint(2, "bad catalog entry length %d\n", blen);
1413 if((blen == Folderlen && t != Folder)
1414 || (blen == Filelen && t != File)){
1415 if(debug) fprint(2, "catalog entry type %d length %d mismatch\n", t, blen);
1418 ino->cnid = get32(b+8);
1419 ino->fileid = ino->cnid;
1420 ino->mtime = gettime(b+16);
1421 ino->ctime = gettime(b+20);
1422 ino->atime = gettime(b+24);
1425 ino->uid = get32(p+0);
1426 ino->gid = get32(p+4);
1427 ino->mode = get16(p+10);
1428 ino->special = get32(p+12);
1430 ino->u.nentries = get32(b+4);
1432 getfork(&ino->u.f.dfork, ino->cnid, Dfork, b+88);
1433 getfork(&ino->u.f.rfork, ino->cnid, Rfork, b+168);
1434 memcpy(ino->u.f.info, b+48, Filen);
1436 ino->u.f.fork = &ino->u.f.dfork;
1442 getcatalogthread(Catalogkey *k, uchar *b, int blen)
1446 if(blen > 10+2*NAMELEN){
1447 if(debug) fprint(2, "bad catalog thread length %d\n", blen);
1451 if(t != FolderThread && t != FileThread){
1452 if(debug) fprint(2, "bad catalog thread type %d\n", t);
1455 return getcatalogkey(k, b+2, blen-2, 1);
1459 getcatalogkey(Catalogkey *k, uchar *b, int blen, int decode)
1461 if(blen > 8+2*NAMELEN){
1462 if(debug) fprint(2, "bad catalog key length %d\n", blen);
1465 k->parent = get32(b+2);
1467 return getname(&k->u.name, b+6);
1473 getname(Name *n, uchar *b)
1478 if(n->len > NAMELEN){
1479 if(debug) fprint(2, "bad name length %d\n", n->len);
1483 for(i=0; i<n->len; i++, b += 2)
1484 n->name[i] = get16(b);
1491 return get32(b) - 2082844800;
1497 return ((u64int)get32(b))<<32 | get32(b+4);
1503 return b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
1509 return b[0]<<8 | b[1];
1513 put32(uchar *b, u32int n)
1522 Adapted from FastUnicodeCompare in Apple technical note 1150.
1527 /* High-byte indices ( == 0 iff no case mapping and no ignorables ) */
1529 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
1530 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1531 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1532 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1533 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1534 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1535 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1536 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1537 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1538 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1539 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1540 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1541 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1542 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1543 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1544 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1545 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1546 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1547 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1548 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1549 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1550 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1551 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1552 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1553 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1554 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1555 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1556 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1557 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1558 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1559 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1560 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
1562 /* Table 1 (for high byte 0x00) */
1564 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
1565 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
1566 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
1567 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
1568 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1569 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
1570 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1571 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
1572 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1573 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
1574 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1575 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
1576 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1577 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
1578 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1579 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
1580 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
1581 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
1582 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
1583 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
1584 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
1585 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
1586 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
1587 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
1588 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7,
1589 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
1590 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
1591 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
1592 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
1593 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
1594 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
1595 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
1597 /* Table 2 (for high byte 0x01) */
1599 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
1600 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
1601 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117,
1602 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
1603 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127,
1604 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
1605 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
1606 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
1607 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
1608 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
1609 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157,
1610 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
1611 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167,
1612 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
1613 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177,
1614 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
1615 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
1616 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
1617 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
1618 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
1619 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
1620 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
1621 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
1622 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
1623 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
1624 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
1625 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7,
1626 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
1627 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7,
1628 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
1629 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7,
1630 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
1632 /* Table 3 (for high byte 0x03) */
1634 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
1635 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
1636 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
1637 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
1638 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
1639 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
1640 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
1641 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
1642 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
1643 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
1644 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
1645 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
1646 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
1647 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
1648 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
1649 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
1650 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
1651 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
1652 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
1653 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
1654 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
1655 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
1656 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
1657 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
1658 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
1659 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
1660 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
1661 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
1662 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
1663 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
1664 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
1665 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
1667 /* Table 4 (for high byte 0x04) */
1669 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407,
1670 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
1671 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
1672 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
1673 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
1674 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
1675 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
1676 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
1677 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
1678 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
1679 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
1680 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
1681 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
1682 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
1683 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477,
1684 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
1685 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
1686 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
1687 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
1688 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
1689 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
1690 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
1691 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
1692 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
1693 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
1694 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
1695 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7,
1696 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
1697 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7,
1698 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
1699 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7,
1700 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
1702 /* Table 5 (for high byte 0x05) */
1704 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
1705 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
1706 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
1707 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
1708 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
1709 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
1710 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
1711 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
1712 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
1713 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
1714 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
1715 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
1716 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
1717 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
1718 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
1719 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
1720 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
1721 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
1722 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
1723 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
1724 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
1725 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
1726 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
1727 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
1728 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
1729 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
1730 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
1731 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
1732 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
1733 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
1734 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
1735 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
1737 /* Table 6 (for high byte 0x10) */
1739 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
1740 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
1741 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
1742 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
1743 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
1744 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
1745 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
1746 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
1747 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
1748 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
1749 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
1750 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
1751 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
1752 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
1753 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
1754 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
1755 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
1756 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
1757 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
1758 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
1759 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
1760 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
1761 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
1762 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
1763 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
1764 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
1765 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
1766 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
1767 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
1768 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
1769 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
1770 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
1772 /* Table 7 (for high byte 0x20) */
1774 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
1775 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
1776 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
1777 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
1778 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
1779 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
1780 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
1781 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
1782 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
1783 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
1784 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
1785 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
1786 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067,
1787 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1788 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077,
1789 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
1790 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
1791 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
1792 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097,
1793 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
1794 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7,
1795 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
1796 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7,
1797 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
1798 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
1799 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
1800 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
1801 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
1802 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7,
1803 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
1804 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7,
1805 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
1807 /* Table 8 (for high byte 0x21) */
1809 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
1810 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
1811 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
1812 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
1813 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
1814 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
1815 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
1816 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
1817 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
1818 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
1819 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
1820 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
1821 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
1822 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
1823 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
1824 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
1825 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
1826 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
1827 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
1828 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
1829 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
1830 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
1831 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
1832 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
1833 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
1834 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
1835 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
1836 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
1837 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
1838 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
1839 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
1840 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
1842 /* Table 9 (for high byte 0xFE) */
1844 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07,
1845 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
1846 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17,
1847 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
1848 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27,
1849 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
1850 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37,
1851 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
1852 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47,
1853 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
1854 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57,
1855 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
1856 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67,
1857 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
1858 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77,
1859 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
1860 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87,
1861 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
1862 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97,
1863 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
1864 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
1865 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
1866 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7,
1867 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
1868 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7,
1869 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
1870 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7,
1871 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
1872 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7,
1873 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
1874 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7,
1875 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
1877 /* Table 10 (for high byte 0xFF) */
1879 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
1880 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
1881 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
1882 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
1883 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
1884 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
1885 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
1886 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
1887 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
1888 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
1889 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
1890 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
1891 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
1892 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
1893 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
1894 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
1895 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
1896 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
1897 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
1898 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
1899 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
1900 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
1901 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
1902 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
1903 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
1904 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
1905 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
1906 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
1907 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
1908 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
1909 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
1910 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
1918 i = hfslcase[(c>>8)&255];
1921 return hfslcase[i+(c&255)];
1925 hfsinamecmp(Name *a, Name *b)
1927 int an, bn, ac, bc, diff;
1956 hfsnamecmp(Name *a, Name *b)
1967 for(; n>0; n--, ap++, bp++){
1973 diff = a->len - b->len;