DragonFly BSD
DragonFly submit List (threaded) for 2003-11
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: kern.file weirdness


From: Eirik Nygaard <eirikn@xxxxxxxxxxxx>
Date: Sun, 23 Nov 2003 12:09:53 +0100

On Sun, Nov 23, 2003 at 09:01:19AM +0900, YONETANI Tomokazu wrote:
> On Sat, Nov 22, 2003 at 02:22:57PM +0100, Eirik Nygaard wrote:
> > On Sat, Nov 22, 2003 at 10:08:57PM +0900, YONETANI Tomokazu wrote:
> > > Hello.
> > > 
> > > On Sat, Nov 22, 2003 at 11:53:30AM +0100, Eirik Nygaard wrote:
> > > > I am working on removing perlism in userland and have come over a little
> > > > problem when I am rewriting sockstat. I try to get all the open fd's from
> > > > the kern.file sysctl with this code:
[ ... ]
> > > > 
> > > > but it only gives me bogus results for some reason.
> > > > 
> > > > Output: 
> > > > Type: -16333
> > > > Type: -14424
> > > > [...]
> > > > Type: -14424
> > > > 
> > > > Would be grateful if someone knows what I am doing wrong here.
> > > 
> > > FreeBSD-current's version of sockstat has a block of code
> > > which looks like this:
> > > 
[ ... ]
> > > 
> > > i.e., you must resize the buffer until sysctlbyname() fails with
> > > ENOMEM.
> > 
> > If you check out the manpage for sysctlbyname it states:
> >      The size of the available data can be determined by calling sysctl() with
> >      the NULL argument for oldp.  The size of the available data will be
> >      returned in the location pointed to by oldlenp.  For some operations, the
> >      amount of space may change often.  For these operations, the system
> >      attempts to round up so that the returned size is large enough for a call
> >      to return the data shortly thereafter.
> > 
> > so I think it is something else, but thanks for the tip.
> 
> Ah, I didn't even understand your question, sorry. Please do
> 
>     less +/^sysctl_kern_file /sys/kern/kern_descrip.c
> 
> And you'll notice why the returned array has an extra garbage(filehead)
> in front of it.
> 
> |	error = SYSCTL_OUT(req, (caddr_t)&filehead, sizeof(filehead));
> |	if (error)
> |		return (error);
> |
> |	/*
> |	 * followed by an array of file structures
> |	 */
> |	LIST_FOREACH(fp, &filehead, f_list) {
> |		error = SYSCTL_OUT(req, (caddr_t)fp, sizeof (struct file));
> |		if (error)
> |			return (error);
> |	}
> |	return (0);
> |}
> 
> So you can rewrite your example code to something like this:
> 
> void
> get_files(void)
> {
> 	struct {
> 		struct filelist head;
> 		struct file array[1];
> 	} *files;
> 	struct file *f;
> 	size_t size;
> 	int i;
> 	
> 	if (sysctlbyname("kern.file", NULL, &size, NULL, 0) < 0)
> 		err(1, "sysctlbyname()");
> 	if ((files = malloc(size)) == NULL)
> 		err(1, "malloc()");
> 	if (sysctlbyname("kern.file", files, &size, NULL, 0) < 0) 
> 		err(1, "sysctlbyname()");
> 	nfiles = (size - sizeof(files->head)) / (sizeof files->array[0]);
> 	for(f = files->array; f < files->array + nfiles; ++f)
> 		printf("Type: %d\n", f->f_type);
> }
> 
> FreeBSD-CURRENT's version of `sysctl -b kern.file' returns just an
> array of struct xfile, so your code could be simpler(but making
> sysctl_kern_file messy).
> 
> 

Of course!
I missed the struct filelist head when I looked at that command. Thanks.
Works like a charm now. :)

-- 
Eirik Nygaard
eirikn@xxxxxxxxxxxx

Attachment: pgp00012.pgp
Description: PGP signature



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]