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