Re: where is fstat
Re: where is fstat
- Subject: Re: where is fstat
- From: Terry Lambert <email@hidden>
- Date: Fri, 16 Jan 2009 17:16:19 -0800
On Jan 16, 2009, at 12:37 PM, Joel Reymont wrote:
On Jan 16, 2009, at 8:25 PM, Jason Coco wrote:
It's a syscall, so it's only a stub in libc. It's actually defined
in the kernel (the xnu module).
A follow-up question then... under what conditions can fstat return
EINVAL (invalid argument)?
I can call fstat for stdin, stdout and stderr just fine but as soon
as I give it my fd (opened read-only), it gives me an error.
I'll go dig through the kernel sources in the meantime.
There is a lot of block comment documentation in xnu in bsd/kern/
kern_descrip.c on fstat which tells what error codes can come from
where. Unless you are calling this on a weird descriptor, here are
the documented returns:
* Returns: 0 Success
* EBADF
* EFAULT
* fp_lookup:EBADF Bad file descriptor
* vnode_getwithref:???
* copyout:EFAULT
* vnode_getwithref:???
* vn_stat:???
* soo_stat:???
* pipe_stat:???
* pshm_stat:???
* kqueue_stat:???
The ??? means you're calling it on a weird descriptor, and the code
will return whatever it returns as an implementation detail of the
descriptor. In general, it means code hat a user might supply or an
NKE a user might supply could return a value other than one of the
documented error codes here. Typically, this will only happen if
someone has written a bogus kernel extention, but, hey, we don't know
what code you have loaded into your kernel.
-
Since you came back later and said that the actual call was ftruncate,
not fstat, the function you want to look at is actually implemented in
xnu in bsd/vfs/vfs_syscalls.c. As I did not need the error codes to
change to pass UNIX conformance testing, I didn't not check the origin
of the error code and trace them back to their distal causes in the
functions called from that function.
In general, though, its:
EINVAL (you told it to truncate to a negative length)
fp_lookup:EBADF
pshm_truncate:EINVAL (the shared memory segment was already deleted;
release your reference, already!)
pshm_truncate:EINVAL (the shared memory segment was allocated, but
you're failed to initialize it yet)
pshm_truncate:EINVAL (mach_make_memory_entry_64 failed, probably
because you initialized things wrong)
pshm_truncate:ENOMEM (there isn't enough memory; maybe you need to
buy more RAM or compile 64 bit?)
pshm_truncate:EACCES (it's not mapped for that)
EINVAL (you told it to truncate a file type that wasn't a vnode or
POSIX shared memory segment)
EINVAL (you told it to truncate a vnode, but you didn't open the file
for write)
vnode_getwithref:EINVAL (the file is not open for write)
vnode_getwithref:ENOENT (your node is dead, probably because your FS
is corrupted)
vnode_setattr:EROFS (you told it to truncate a read-only file; you
can't expect to write ROMs)
vnode_setattr:??? (whatever the filesystem implementation can return
for VNOP_SETATTR; if iit's one of ours, this won't happen)
Also, on the detrace question:
You want to do what's called a speculative function boundary trace,
and check the error return on the function you are tracing for EINVAL;
if you get an EINVAL, then commit the speculative trace, otherwise,
discard it. When you get output for the speculative trace, then it
will be the call stack that resulted in the EINVAL being returned.
In general, since the error code being returned is not examined/set
with an accessor/mutator function, and if it were, the function would
most likely be inlined, there's not really a tracepoint for you to
trap on in order to trace such things (one of the many reasons
programmers should not use data interfaces for important things, and
one of the many performance reasons that they do anyway).
However, even if you got a trace on the EINVAL set point, that would
only give you a proximal cause ("something failed somewhere down the
call stack, and that error eventuall bubbled up to here, so I set the
BSD error code EINVAL"), so a speculative trace would really be the
best way to go in any case.
There are a lot of really good examples of how to use this in the Sun
DTrace guide.
PS: My wild educated guess is you are passing a negative number to the
truncate; this will typically happen if you attempt to use something
other than an off_t (signed 64 bit) parameter to ftruncate(), and
failed to have a prototype in scope at the time you made the call, and
then half your 32 bit value happens to be whatever 32 bits of garbage
were already in the other register -- you can compile with -Wall -
Werror compiler options to catch things like this at compile time.
-- Terry
_______________________________________________
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