Re: Identifying sparse files using getattrlist()
Re: Identifying sparse files using getattrlist()
- Subject: Re: Identifying sparse files using getattrlist()
- From: Alastair Houghton <email@hidden>
- Date: Wed, 4 Nov 2009 10:12:42 +0000
On 4 Nov 2009, at 08:41, rohan a wrote:
However, for a sparse file this continues to return same sizes for
stat size and real size. This is an Apple UFS partition.
As I said before, the thing to do is to look at the kernel sources.
It's amazing how much of their own time some people are prepared to
waste... it took me less than five minutes to figure out the answer to
your question, and in the meantime I bet you've spent a lot longer
than that on it.
Anyway, the answer is that (a) stat() won't return the information you
want, and (b) you're using the wrong attribute for getattrlist(). You
want ATTR_FILE_DATAALLOCSIZE, not ATTR_FILE_ALLOCSIZE.
FYI, you can work this out by looking at vfs_attrlist.c (in bsd/vfs),
where you'll see that getattrlist() uses vnode_getattr(), which you
can see from the table in bsd/ufs/ffs/ffs_vnops.c maps to ufs_getattr
(). (That's kind of unsurprising, so you could skip that part if you
wanted.)
Anyway, ufs_getattr() is in ufs_vnops.c (in bsd/ufs/ufs/ufs_vnops.c),
and there you can see it copying the data out of its inode structure.
The potentially interesting lines are:
VATTR_RETURN(vap, va_data_size, ip->i_din.di_size);
and
VATTR_RETURN(vap, va_data_alloc, dbtob((u_quad_t)ip->i_blocks,
devBlockSize));
So next we need to look in inode.h to see what the ip->i_din.di_size
and ip->i_blocks fields actually contain. We find that i_blocks is
just a #define:
#define i_blocks i_din.di_blocks
So now we're interested in the i_din member of struct inode, which is
a struct dinode. struct dinode is in dinode.h, so we open that up and
discover:
u_int64_t di_size; /* 8: File byte count. */
and
u_int32_t di_blocks; /* 104: Blocks actually held. */
in struct dinode.
So va_data_alloc is what you're interested in, and if you look back at
the vfs_attrlist.c file, you'll find that at the top there is a list
mapping the getattrlist() constants to the va_ names.
In case you're wondering how the ATTR_FILE_TOTALSIZE works for ufs
when ufs_getattr() clearly doesn't bother returning it, for that you
need to look in kpi_vfs.c, at vnode_getattr(), where you'll see that
the vnode_getattr() function fills in various things automatically if
the underlying filesystem didn't do it.
All of this also explains why stat(), which uses vn_stat() (in
vfs_vnops.c), won't work. stat() asks for va_data_size and
va_total_alloc. UFS doesn't return va_total_alloc, so it's computed
in vnode_getattr() by copying from va_data_size. Hence you're going
to get the same data in both places.
I suppose there's an argument that va_total_alloc should be computed
from va_data_alloc rather than va_data_size if the former is defined,
but you'd have to take that up with Apple, and I don't fancy your
chances because UFS is pretty old and largely unused at this point.
Anyway, it took me longer to write this e-mail than it did to work all
that out, and even if it had taken you twice as long as it took me to
find all of this, it would have been faster for you...
Kind regards,
Alastair.
--
http://alastairs-place.net
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden