mac resource fork - from Dave Swasey
This commit is contained in:
parent
001dc1709b
commit
63408c39a1
4 changed files with 203 additions and 69 deletions
|
|
@ -594,6 +594,7 @@ ext2readdir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u64int coo
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
if(cookie >= ino.size){
|
if(cookie >= ino.size){
|
||||||
|
*peof = 1;
|
||||||
*pcount = 0;
|
*pcount = 0;
|
||||||
*pdata = 0;
|
*pdata = 0;
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
|
|
|
||||||
|
|
@ -696,6 +696,7 @@ ffsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count, u64int cook
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
if(cookie >= ino.size){
|
if(cookie >= ino.size){
|
||||||
|
*peof = 1;
|
||||||
*pcount = 0;
|
*pcount = 0;
|
||||||
*pdata = 0;
|
*pdata = 0;
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2007 David Swasey; see COPYRIGHT.
|
Copyright (c) 2007 David Swasey; see COPYRIGHT.
|
||||||
Limitations:
|
Limitations:
|
||||||
Resource forks are hidden.
|
|
||||||
Hfsreaddir skips entries whose names contain NUL.
|
Hfsreaddir skips entries whose names contain NUL.
|
||||||
Simulated hard links are ignored.
|
Simulated hard links are ignored.
|
||||||
Hfsbadblock is untested.
|
Hfsbadblock is untested.
|
||||||
|
|
@ -17,6 +16,9 @@
|
||||||
|
|
||||||
#define debug 0
|
#define debug 0
|
||||||
|
|
||||||
|
static char Rprefix[] = "._";
|
||||||
|
enum { Rplen = nelem(Rprefix)-1 };
|
||||||
|
|
||||||
static int hfssync(Fsys*);
|
static int hfssync(Fsys*);
|
||||||
static int hfswrapper(Fsys*);
|
static int hfswrapper(Fsys*);
|
||||||
static int hfstreesync(Hfs*, Fork*, Tree*, int);
|
static int hfstreesync(Hfs*, Fork*, Tree*, int);
|
||||||
|
|
@ -27,6 +29,7 @@ static Nfs3Status hfsroot(Fsys*, Nfs3Handle*);
|
||||||
static Nfs3Status hfsgetattr(Fsys*, SunAuthUnix*, Nfs3Handle*, Nfs3Attr*);
|
static Nfs3Status hfsgetattr(Fsys*, SunAuthUnix*, Nfs3Handle*, Nfs3Attr*);
|
||||||
static Nfs3Status hfsaccess(Fsys *fsys, SunAuthUnix*, Nfs3Handle *, u32int, u32int*, Nfs3Attr *attr);
|
static Nfs3Status hfsaccess(Fsys *fsys, SunAuthUnix*, Nfs3Handle *, u32int, u32int*, Nfs3Attr *attr);
|
||||||
static Nfs3Status hfslookup(Fsys*, SunAuthUnix*, Nfs3Handle*, char*, Nfs3Handle*);
|
static Nfs3Status hfslookup(Fsys*, SunAuthUnix*, Nfs3Handle*, char*, Nfs3Handle*);
|
||||||
|
static Nfs3Status _hfslookup(Hfs*, u32int, char*, Catalogkey*, Treeref*);
|
||||||
static Nfs3Status hfsreaddir(Fsys *fsys, SunAuthUnix*, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*);
|
static Nfs3Status hfsreaddir(Fsys *fsys, SunAuthUnix*, Nfs3Handle *h, u32int, u64int, uchar**, u32int*, u1int*);
|
||||||
static Nfs3Status hfsreadfile(Fsys*, SunAuthUnix*, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*);
|
static Nfs3Status hfsreadfile(Fsys*, SunAuthUnix*, Nfs3Handle*, u32int, u64int, uchar**, u32int*, u1int*);
|
||||||
static Nfs3Status hfsreadlink(Fsys*, SunAuthUnix*, Nfs3Handle*, char**);
|
static Nfs3Status hfsreadlink(Fsys*, SunAuthUnix*, Nfs3Handle*, char**);
|
||||||
|
|
@ -58,6 +61,7 @@ static u32int gettime(uchar*);
|
||||||
static u64int get64(uchar*);
|
static u64int get64(uchar*);
|
||||||
static u32int get32(uchar*);
|
static u32int get32(uchar*);
|
||||||
static int get16(uchar*);
|
static int get16(uchar*);
|
||||||
|
static void put32(uchar*, u32int);
|
||||||
|
|
||||||
static int hfsinamecmp(Name*, Name*);
|
static int hfsinamecmp(Name*, Name*);
|
||||||
static int hfsnamecmp(Name*, Name*);
|
static int hfsnamecmp(Name*, Name*);
|
||||||
|
|
@ -309,57 +313,80 @@ hfsblockread(Fsys *fsys, u64int vbno)
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
mkhandle(Nfs3Handle *h, u32int cnid)
|
hasresource(Inode *ino)
|
||||||
{
|
{
|
||||||
h->h[0] = cnid >> 24;
|
return (ino->mode&IFMT)==IFREG && ino->rfork.size>0;
|
||||||
h->h[1] = cnid >> 16;
|
}
|
||||||
h->h[2] = cnid >> 8;
|
|
||||||
h->h[3] = cnid;
|
static void
|
||||||
h->len = 4;
|
useresource(Inode *ino)
|
||||||
|
{
|
||||||
|
ino->fileid = ((u64int)1)<<32 | ino->cnid;
|
||||||
|
ino->nhdr = Adlen;
|
||||||
|
ino->fork = &ino->rfork;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mkhandle(Nfs3Handle *h, int rsrc, u32int cnid)
|
||||||
|
{
|
||||||
|
h->h[0] = rsrc;
|
||||||
|
put32(h->h+1, cnid);
|
||||||
|
h->len = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Nfs3Status
|
static Nfs3Status
|
||||||
hfsroot(Fsys *fsys, Nfs3Handle *h)
|
hfsroot(Fsys *fsys, Nfs3Handle *h)
|
||||||
{
|
{
|
||||||
USED(fsys);
|
USED(fsys);
|
||||||
mkhandle(h, RootId);
|
mkhandle(h, 0, RootId);
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Nfs3Status
|
static Nfs3Status
|
||||||
handle2ino(Hfs *fs, Nfs3Handle *h, u32int *parent, Treeref *ref, Inode *ino)
|
handle2ino(Hfs *fs, Nfs3Handle *h, Treeref *ref, Catalogkey *key, Inode *ino)
|
||||||
{
|
{
|
||||||
Treeref refbuf;
|
Treeref refbuf;
|
||||||
u32int cnid;
|
u32int cnid;
|
||||||
Catalogkey key;
|
Catalogkey keybuf;
|
||||||
|
int rsrc;
|
||||||
|
|
||||||
|
if(h->len != 5)
|
||||||
|
return Nfs3ErrBadHandle;
|
||||||
|
rsrc = h->h[0];
|
||||||
|
cnid = get32(h->h+1);
|
||||||
|
if(debug) print("cnid %ud%s...", cnid, rsrc ? " rsrc" : "");
|
||||||
|
|
||||||
if(ref == nil)
|
if(ref == nil)
|
||||||
ref = &refbuf;
|
ref = &refbuf;
|
||||||
|
if(key == nil)
|
||||||
if(h->len != 4)
|
key = &keybuf;
|
||||||
return Nfs3ErrBadHandle;
|
|
||||||
cnid = get32(h->h);
|
|
||||||
if(debug) print("cnid %ud...", cnid);
|
|
||||||
|
|
||||||
/* map cnid to full catalog key */
|
/* map cnid to full catalog key */
|
||||||
key.parent = cnid;
|
key->parent = cnid;
|
||||||
key.name.len = 0;
|
key->name.len = 0;
|
||||||
if(hfscatsearch(fs, &key, ref) < 0)
|
if(hfscatsearch(fs, key, ref) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if(getcatalogthread(&key, ref->data, ref->dlen) < 0)
|
if(getcatalogthread(key, ref->data, ref->dlen) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
hfsrefput(ref);
|
hfsrefput(ref);
|
||||||
|
|
||||||
if(debug) print("{%ud,%.*S}...", key.parent, key.name.len, key.name.name);
|
if(debug) print("{%ud,%.*S}...", key->parent, key->name.len, key->name.name);
|
||||||
|
|
||||||
/* map full key to catalog info */
|
/* map full key to catalog info */
|
||||||
if(hfscatsearch(fs, &key, ref) < 0)
|
if(hfscatsearch(fs, key, ref) < 0)
|
||||||
goto error;
|
|
||||||
if(parent)
|
|
||||||
*parent = key.parent;
|
|
||||||
if(ino != nil && getcatalogrecord(ino, ref->data, ref->dlen) < 0)
|
|
||||||
goto error;
|
goto error;
|
||||||
|
if(ino != nil){
|
||||||
|
if(getcatalogrecord(ino, ref->data, ref->dlen) < 0)
|
||||||
|
goto error;
|
||||||
|
if(rsrc){
|
||||||
|
if(!hasresource(ino)){
|
||||||
|
hfsrefput(ref);
|
||||||
|
return Nfs3ErrBadHandle;
|
||||||
|
}
|
||||||
|
useresource(ino);
|
||||||
|
}
|
||||||
|
}
|
||||||
if(ref == &refbuf)
|
if(ref == &refbuf)
|
||||||
hfsrefput(ref);
|
hfsrefput(ref);
|
||||||
|
|
||||||
|
|
@ -408,8 +435,8 @@ ino2attr(Hfs *fs, Inode *ino, Nfs3Attr *attr)
|
||||||
attr->uid = ino->uid;
|
attr->uid = ino->uid;
|
||||||
attr->gid = ino->gid;
|
attr->gid = ino->gid;
|
||||||
if(attr->type==Nfs3FileReg || attr->type==Nfs3FileSymlink){
|
if(attr->type==Nfs3FileReg || attr->type==Nfs3FileSymlink){
|
||||||
attr->size = ino->dfork.size;
|
attr->size = ino->nhdr+ino->fork->size;
|
||||||
attr->used = (u64int)ino->dfork.nblocks*fs->blocksize;
|
attr->used = (u64int)ino->fork->nblocks*fs->blocksize;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
attr->size = 0;
|
attr->size = 0;
|
||||||
|
|
@ -424,7 +451,7 @@ ino2attr(Hfs *fs, Inode *ino, Nfs3Attr *attr)
|
||||||
attr->minor = 0;
|
attr->minor = 0;
|
||||||
}
|
}
|
||||||
attr->fsid = 0;
|
attr->fsid = 0;
|
||||||
attr->fileid = ino->cnid;
|
attr->fileid = ino->fileid;
|
||||||
attr->atime.sec = ino->atime;
|
attr->atime.sec = ino->atime;
|
||||||
attr->atime.nsec = 0;
|
attr->atime.nsec = 0;
|
||||||
attr->mtime.sec = ino->mtime;
|
attr->mtime.sec = ino->mtime;
|
||||||
|
|
@ -550,14 +577,14 @@ static Nfs3Status
|
||||||
hfslookup(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char *name, Nfs3Handle *nh)
|
hfslookup(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char *name, Nfs3Handle *nh)
|
||||||
{
|
{
|
||||||
Hfs *fs;
|
Hfs *fs;
|
||||||
u32int parent;
|
|
||||||
Inode ino, target;
|
Inode ino, target;
|
||||||
Nfs3Status ok;
|
Nfs3Status ok;
|
||||||
Catalogkey key;
|
Catalogkey key;
|
||||||
Treeref ref;
|
Treeref ref;
|
||||||
|
int rsrc;
|
||||||
|
|
||||||
fs = fsys->priv;
|
fs = fsys->priv;
|
||||||
if((ok = handle2ino(fs, h, &parent, nil, &ino)) != Nfs3Ok)
|
if((ok = handle2ino(fs, h, nil, &key, &ino)) != Nfs3Ok)
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
if((ino.mode&IFMT) != IFDIR)
|
if((ino.mode&IFMT) != IFDIR)
|
||||||
|
|
@ -567,22 +594,28 @@ hfslookup(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, char *name, Nfs3Handle *nh
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
if(strcmp(name, ".") == 0){
|
if(strcmp(name, ".") == 0){
|
||||||
mkhandle(nh, ino.cnid);
|
mkhandle(nh, 0, ino.cnid);
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
}
|
}
|
||||||
if(strcmp(name, "..") == 0){
|
if(strcmp(name, "..") == 0){
|
||||||
mkhandle(nh, parent);
|
mkhandle(nh, 0, key.parent);
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
}
|
}
|
||||||
key.parent = ino.cnid;
|
|
||||||
if((ok = utf2name(&key.name, name)) != Nfs3Ok)
|
rsrc = 0;
|
||||||
return ok;
|
if((ok = _hfslookup(fs, ino.cnid, name, &key, &ref)) != Nfs3Ok){
|
||||||
if(hfscatsearch(fs, &key, &ref) < 0)
|
if(memcmp(name, Rprefix, Rplen)==0
|
||||||
return Nfs3ErrNoEnt;
|
&& _hfslookup(fs, ino.cnid, name+Rplen, &key, &ref)==Nfs3Ok)
|
||||||
|
rsrc = 1;
|
||||||
|
else
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
if(getcatalogrecord(&target, ref.data, ref.dlen) < 0)
|
if(getcatalogrecord(&target, ref.data, ref.dlen) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
hfsrefput(&ref);
|
hfsrefput(&ref);
|
||||||
mkhandle(nh, target.cnid);
|
if(rsrc && !hasresource(&target))
|
||||||
|
return Nfs3ErrNoEnt;
|
||||||
|
mkhandle(nh, rsrc, target.cnid);
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
@ -590,6 +623,20 @@ error:
|
||||||
return Nfs3ErrIo;
|
return Nfs3ErrIo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Nfs3Status
|
||||||
|
_hfslookup(Hfs *fs, u32int parent, char *name, Catalogkey *key, Treeref *ref)
|
||||||
|
{
|
||||||
|
Nfs3Status ok;
|
||||||
|
|
||||||
|
key->parent = parent;
|
||||||
|
if((ok = utf2name(&key->name, name)) != Nfs3Ok)
|
||||||
|
return ok;
|
||||||
|
if(hfscatsearch(fs, key, ref) < 0)
|
||||||
|
return Nfs3ErrNoEnt;
|
||||||
|
return Nfs3Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For the moment, hfsreaddir does not return entries whose names
|
For the moment, hfsreaddir does not return entries whose names
|
||||||
contain NUL, avoiding errors like "ls: : No such file or
|
contain NUL, avoiding errors like "ls: : No such file or
|
||||||
|
|
@ -615,11 +662,13 @@ hfsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
|
||||||
Treeref ref;
|
Treeref ref;
|
||||||
Catalogkey key;
|
Catalogkey key;
|
||||||
Nfs3Entry e;
|
Nfs3Entry e;
|
||||||
char name[UTFNAMELEN];
|
int rsrc;
|
||||||
|
char name[Rplen+UTFNAMELEN];
|
||||||
uchar *dp, *dep, *ndp, *data;
|
uchar *dp, *dep, *ndp, *data;
|
||||||
Hfs *fs;
|
Hfs *fs;
|
||||||
Inode ino, child;
|
Inode ino, child;
|
||||||
Nfs3Status ok;
|
Nfs3Status ok;
|
||||||
|
u32int nentries;
|
||||||
|
|
||||||
fs = fsys->priv;
|
fs = fsys->priv;
|
||||||
if((ok = handle2ino(fs, h, nil, nil, &ino)) != Nfs3Ok)
|
if((ok = handle2ino(fs, h, nil, nil, &ino)) != Nfs3Ok)
|
||||||
|
|
@ -631,10 +680,15 @@ hfsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
|
||||||
if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
|
if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
|
if(ino.nentries>>31)
|
||||||
|
return Nfs3ErrIo;
|
||||||
|
nentries = ino.nentries*2; /* even data, odd resource */
|
||||||
|
|
||||||
i = cookie>>32;
|
i = cookie>>32;
|
||||||
cnid = cookie&0xFFFFFFFF;
|
cnid = cookie&0xFFFFFFFF;
|
||||||
if(debug) print("readdir %ud %ud %ud...", cnid, i, ino.nentries);
|
if(debug) print("readdir %ud %ud %ud...", cnid, i, nentries);
|
||||||
if(i > ino.nentries){
|
if(i >= nentries){
|
||||||
|
*peof = 1;
|
||||||
*pcount = 0;
|
*pcount = 0;
|
||||||
*pdata = nil;
|
*pdata = nil;
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
|
|
@ -658,58 +712,98 @@ hfsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
mkhandle(&ch, cnid);
|
mkhandle(&ch, i&1, cnid);
|
||||||
if((ok = handle2ino(fs, &ch, nil, &ref, nil)) != Nfs3Ok)
|
if((ok = handle2ino(fs, &ch, &ref, &key, &child)) != Nfs3Ok)
|
||||||
return ok;
|
return ok;
|
||||||
|
if(key.parent != ino.cnid)
|
||||||
|
goto badparent;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&e, 0, sizeof e);
|
memset(&e, 0, sizeof e);
|
||||||
for(; i<ino.nentries; i++){
|
for(; i<nentries; i++){
|
||||||
if(hfsrefnextrec(&ref) < 0)
|
rsrc = i&1;
|
||||||
goto error;
|
if(!rsrc){
|
||||||
if(getcatalogkey(&key, ref.key, ref.klen, 1) < 0)
|
if(hfsrefnextrec(&ref) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if(key.parent != ino.cnid){
|
if(getcatalogkey(&key, ref.key, ref.klen, 1) < 0)
|
||||||
if(debug) fprint(2, "%.*S: bad parent %ud != %ud\n",
|
goto error;
|
||||||
key.name.len, key.name.name, key.parent, ino.cnid);
|
if(key.parent != ino.cnid)
|
||||||
goto error;
|
goto badparent;
|
||||||
|
if(getcatalogrecord(&child, ref.data, ref.dlen) < 0)
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
if(getcatalogrecord(&child, ref.data, ref.dlen) < 0)
|
else if(!hasresource(&child))
|
||||||
goto error;
|
continue;
|
||||||
|
else
|
||||||
|
useresource(&child);
|
||||||
if(hfshidename(&key.name))
|
if(hfshidename(&key.name))
|
||||||
continue;
|
continue;
|
||||||
if(debug) print("{%ud,%ud,%.*S} ",
|
e.fileid = child.fileid;
|
||||||
i, child.cnid, key.name.len, key.name.name);
|
|
||||||
e.fileid = child.cnid;
|
|
||||||
e.name = name;
|
e.name = name;
|
||||||
e.namelen = name2utf(name, &key.name);
|
if(rsrc){
|
||||||
|
memcpy(name, Rprefix, Rplen);
|
||||||
|
e.namelen = Rplen+name2utf(name+Rplen, &key.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
e.namelen = name2utf(name, &key.name);
|
||||||
e.cookie = ((u64int)i)<<32 | child.cnid;
|
e.cookie = ((u64int)i)<<32 | child.cnid;
|
||||||
e.haveAttr = (ino2attr(fs, &child, &e.attr) == Nfs3Ok);
|
e.haveAttr = (ino2attr(fs, &child, &e.attr) == Nfs3Ok);
|
||||||
e.haveHandle = 1;
|
e.haveHandle = 1;
|
||||||
mkhandle(&e.handle, child.cnid);
|
mkhandle(&e.handle, rsrc, child.cnid);
|
||||||
|
if(debug) print("%s/0x%llux ", e.name, e.fileid);
|
||||||
if(nfs3entrypack(dp, dep, &ndp, &e) < 0)
|
if(nfs3entrypack(dp, dep, &ndp, &e) < 0)
|
||||||
break;
|
break;
|
||||||
dp = ndp;
|
dp = ndp;
|
||||||
}
|
}
|
||||||
hfsrefput(&ref);
|
hfsrefput(&ref);
|
||||||
if(i == ino.nentries)
|
if(i == nentries)
|
||||||
*peof = 1;
|
*peof = 1;
|
||||||
*pcount = dp - data;
|
*pcount = dp - data;
|
||||||
*pdata = data;
|
*pdata = data;
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
|
|
||||||
|
badparent:
|
||||||
|
if(debug) fprint(2, "%.*S: bad parent %ud != %ud\n",
|
||||||
|
key.name.len, key.name.name, key.parent, ino.cnid);
|
||||||
error:
|
error:
|
||||||
hfsrefput(&ref);
|
hfsrefput(&ref);
|
||||||
return Nfs3ErrIo;
|
return Nfs3ErrIo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See RFC 1740. */
|
||||||
|
static int
|
||||||
|
appledouble(Inode *ino, uchar *ad)
|
||||||
|
{
|
||||||
|
static uchar Adhdr[Adlen-4-Filen] =
|
||||||
|
{
|
||||||
|
0,5,22,7,0,2,0,0, /* magic */
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* filler */
|
||||||
|
0,2, /* nentries */
|
||||||
|
0,0,0,9, /* magic: finder info */
|
||||||
|
0,0,0,Fioff, /* offset */
|
||||||
|
0,0,0,Filen, /* length */
|
||||||
|
0,0,0,2, /* magic: rfork */
|
||||||
|
0,0,0,Adlen, /* offset */
|
||||||
|
};
|
||||||
|
|
||||||
|
if(ino->rfork.size>>32){
|
||||||
|
if(debug) fprint(2, "resource fork %ud too large\n", ino->cnid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(ad, Adhdr, nelem(Adhdr));
|
||||||
|
put32(ad+nelem(Adhdr), ino->rfork.size);
|
||||||
|
memcpy(ad+Fioff, ino->info, Filen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static Nfs3Status
|
static Nfs3Status
|
||||||
hfsreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
|
hfsreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
|
||||||
u64int offset, uchar **pdata, u32int *pcount, u1int *peof)
|
u64int offset, uchar **pdata, u32int *pcount, u1int *peof)
|
||||||
{
|
{
|
||||||
u64int size;
|
u64int size;
|
||||||
uchar *data;
|
int skip;
|
||||||
|
uchar *data, prefix[Adlen];
|
||||||
Hfs *fs;
|
Hfs *fs;
|
||||||
Inode ino;
|
Inode ino;
|
||||||
Nfs3Status ok;
|
Nfs3Status ok;
|
||||||
|
|
@ -724,7 +818,7 @@ hfsreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
|
||||||
if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
|
if((ok = inoperm(&ino, au, AREAD)) != Nfs3Ok)
|
||||||
return ok;
|
return ok;
|
||||||
|
|
||||||
size = ino.dfork.size;
|
size = ino.nhdr+ino.fork->size;
|
||||||
if(offset >= size){
|
if(offset >= size){
|
||||||
*pdata = 0;
|
*pdata = 0;
|
||||||
*pcount = 0;
|
*pcount = 0;
|
||||||
|
|
@ -736,15 +830,30 @@ hfsreadfile(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h, u32int count,
|
||||||
data = mallocz(count, 1);
|
data = mallocz(count, 1);
|
||||||
if(data == nil)
|
if(data == nil)
|
||||||
return Nfs3ErrNoMem;
|
return Nfs3ErrNoMem;
|
||||||
if(hfsforkread(fs, &ino.dfork, data, count, offset) < 0){
|
if(offset < ino.nhdr){
|
||||||
free(data);
|
if(appledouble(&ino, prefix) < 0)
|
||||||
return Nfs3ErrIo;
|
goto error;
|
||||||
|
skip = Adlen-offset;
|
||||||
|
if(skip > count)
|
||||||
|
skip = count;
|
||||||
|
memcpy(data, prefix+offset, skip);
|
||||||
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
offset -= ino.nhdr;
|
||||||
|
skip = 0;
|
||||||
|
}
|
||||||
|
if(hfsforkread(fs, ino.fork, data+skip, count-skip, offset) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
*peof = (offset+count == size);
|
*peof = (offset+count == size);
|
||||||
*pcount = count;
|
*pcount = count;
|
||||||
*pdata = data;
|
*pdata = data;
|
||||||
return Nfs3Ok;
|
return Nfs3Ok;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(data);
|
||||||
|
return Nfs3ErrIo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Nfs3Status
|
static Nfs3Status
|
||||||
|
|
@ -1242,6 +1351,7 @@ getcatalogrecord(Inode *ino, uchar *b, int blen)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ino->cnid = get32(b+8);
|
ino->cnid = get32(b+8);
|
||||||
|
ino->fileid = ino->cnid;
|
||||||
ino->mtime = gettime(b+16);
|
ino->mtime = gettime(b+16);
|
||||||
ino->ctime = gettime(b+20);
|
ino->ctime = gettime(b+20);
|
||||||
ino->atime = gettime(b+24);
|
ino->atime = gettime(b+24);
|
||||||
|
|
@ -1252,8 +1362,13 @@ getcatalogrecord(Inode *ino, uchar *b, int blen)
|
||||||
ino->special = get32(p+12);
|
ino->special = get32(p+12);
|
||||||
if(t == Folder)
|
if(t == Folder)
|
||||||
ino->nentries = get32(b+4);
|
ino->nentries = get32(b+4);
|
||||||
else
|
else{
|
||||||
getfork(&ino->dfork, ino->cnid, Dfork, b+88);
|
getfork(&ino->dfork, ino->cnid, Dfork, b+88);
|
||||||
|
getfork(&ino->rfork, ino->cnid, Rfork, b+168);
|
||||||
|
memcpy(ino->info, b+48, Filen);
|
||||||
|
ino->nhdr = 0;
|
||||||
|
ino->fork = &ino->dfork;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1328,6 +1443,15 @@ get16(uchar *b)
|
||||||
return b[0]<<8 | b[1];
|
return b[0]<<8 | b[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
put32(uchar *b, u32int n)
|
||||||
|
{
|
||||||
|
b[0] = n>>24;
|
||||||
|
b[1] = n>>16;
|
||||||
|
b[2] = n>>8;
|
||||||
|
b[3] = n;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Adapted from FastUnicodeCompare in Apple technical note 1150.
|
Adapted from FastUnicodeCompare in Apple technical note 1150.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,9 @@ enum
|
||||||
Extentlen = 8, /* Extent */
|
Extentlen = 8, /* Extent */
|
||||||
Ndlen = 14, /* Node */
|
Ndlen = 14, /* Node */
|
||||||
Folderlen = 88, Filelen = 248, /* Inode */
|
Folderlen = 88, Filelen = 248, /* Inode */
|
||||||
|
Adlen = 82, /* Apple double header */
|
||||||
|
Fioff = 50,
|
||||||
|
Filen = 32, /* Finder info */
|
||||||
|
|
||||||
/* values in Node.type */
|
/* values in Node.type */
|
||||||
LeafNode = -1, IndexNode, HeaderNode, MapNode,
|
LeafNode = -1, IndexNode, HeaderNode, MapNode,
|
||||||
|
|
@ -113,6 +116,7 @@ struct Fork
|
||||||
struct Inode
|
struct Inode
|
||||||
{
|
{
|
||||||
u32int cnid;
|
u32int cnid;
|
||||||
|
u64int fileid; /* in memory only */
|
||||||
u32int mtime; /* modification */
|
u32int mtime; /* modification */
|
||||||
u32int ctime; /* attribute modification */
|
u32int ctime; /* attribute modification */
|
||||||
u32int atime; /* access */
|
u32int atime; /* access */
|
||||||
|
|
@ -124,7 +128,12 @@ struct Inode
|
||||||
u32int nentries; /* directories */
|
u32int nentries; /* directories */
|
||||||
struct{ /* files */
|
struct{ /* files */
|
||||||
Fork dfork;
|
Fork dfork;
|
||||||
/*Fork rfork;*/
|
Fork rfork;
|
||||||
|
uchar info[Filen];
|
||||||
|
|
||||||
|
/* in memory only */
|
||||||
|
int nhdr; /* 0 or Adlen */
|
||||||
|
Fork *fork; /* dfork or rfork */
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -204,7 +213,6 @@ struct Hfs
|
||||||
Fork catalogfork;
|
Fork catalogfork;
|
||||||
Tree extents; /* Extentkey -> Extent[NEXTENT] */
|
Tree extents; /* Extentkey -> Extent[NEXTENT] */
|
||||||
Tree catalog; /* Catalogkey -> Catalogkey + Inode */
|
Tree catalog; /* Catalogkey -> Catalogkey + Inode */
|
||||||
int wrapper; /* HFS wrapper used? */
|
|
||||||
Disk *disk;
|
Disk *disk;
|
||||||
Fsys *fsys;
|
Fsys *fsys;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue