diff --git a/lib/libgeom/geom_getxml.c b/lib/libgeom/geom_getxml.c index f3d7ba9deb03..48565f707b03 100644 --- a/lib/libgeom/geom_getxml.c +++ b/lib/libgeom/geom_getxml.c @@ -1,89 +1,89 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-3-Clause-FreeBSD * * Copyright (c) 2003 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include "libgeom.h" /* * Amount of extra space we allocate to try and anticipate the size of * confxml. */ #define GEOM_GETXML_SLACK 4096 /* * Number of times to retry in the face of the size of confxml exceeding * that of our buffer. */ #define GEOM_GETXML_RETRIES 4 char * geom_getxml(void) { char *p; size_t l = 0; int mib[3]; size_t sizep; int retries; sizep = sizeof(mib) / sizeof(*mib); if (sysctlnametomib("kern.geom.confxml", mib, &sizep) != 0) return (NULL); if (sysctl(mib, sizep, NULL, &l, NULL, 0) != 0) return (NULL); l += GEOM_GETXML_SLACK; for (retries = 0; retries < GEOM_GETXML_RETRIES; retries++) { p = malloc(l); if (p == NULL) return (NULL); if (sysctl(mib, sizep, p, &l, NULL, 0) == 0) return (reallocf(p, strlen(p) + 1)); free(p); if (errno != ENOMEM) return (NULL); /* * Our buffer wasn't big enough. Make it bigger and * try again. */ l *= 2; } return (NULL); } diff --git a/lib/libgeom/geom_stats.c b/lib/libgeom/geom_stats.c index 7c9191e29686..e8e2969e835f 100644 --- a/lib/libgeom/geom_stats.c +++ b/lib/libgeom/geom_stats.c @@ -1,192 +1,192 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-3-Clause-FreeBSD * * Copyright (c) 2003 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /************************************************************/ static uint npages, spp; static int pagesize, statsfd = -1; static u_char *statp; void geom_stats_close(void) { if (statsfd == -1) return; munmap(statp, npages * pagesize); statp = NULL; close (statsfd); statsfd = -1; } void geom_stats_resync(void) { void *p; off_t mediasize; int error; if (statsfd == -1) return; error = ioctl(statsfd, DIOCGMEDIASIZE, &mediasize); if (error) err(1, "DIOCGMEDIASIZE(" _PATH_DEV DEVSTAT_DEVICE_NAME ")"); munmap(statp, npages * pagesize); p = mmap(statp, mediasize, PROT_READ, MAP_SHARED, statsfd, 0); if (p == MAP_FAILED) err(1, "mmap(/dev/devstat):"); else { statp = p; npages = mediasize / pagesize; } } int geom_stats_open(void) { int error; void *p; if (statsfd != -1) return (EBUSY); statsfd = open(_PATH_DEV DEVSTAT_DEVICE_NAME, O_RDONLY); if (statsfd < 0) return (errno); pagesize = getpagesize(); spp = pagesize / sizeof(struct devstat); p = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, statsfd, 0); if (p == MAP_FAILED) { error = errno; close(statsfd); statsfd = -1; errno = error; return (error); } statp = p; npages = 1; geom_stats_resync(); return (0); } struct snapshot { u_char *ptr; uint pages; uint pagesize; uint perpage; struct timespec time; /* used by getnext: */ uint u, v; }; void * geom_stats_snapshot_get(void) { struct snapshot *sp; sp = malloc(sizeof *sp); if (sp == NULL) return (NULL); memset(sp, 0, sizeof *sp); sp->ptr = malloc(pagesize * npages); if (sp->ptr == NULL) { free(sp); return (NULL); } explicit_bzero(sp->ptr, pagesize * npages); /* page in, cache */ clock_gettime(CLOCK_REALTIME, &sp->time); memcpy(sp->ptr, statp, pagesize * npages); sp->pages = npages; sp->perpage = spp; sp->pagesize = pagesize; return (sp); } void geom_stats_snapshot_free(void *arg) { struct snapshot *sp; sp = arg; free(sp->ptr); free(sp); } void geom_stats_snapshot_timestamp(void *arg, struct timespec *tp) { struct snapshot *sp; sp = arg; *tp = sp->time; } void geom_stats_snapshot_reset(void *arg) { struct snapshot *sp; sp = arg; sp->u = sp->v = 0; } struct devstat * geom_stats_snapshot_next(void *arg) { struct devstat *gsp; struct snapshot *sp; sp = arg; gsp = (struct devstat *) (sp->ptr + sp->u * pagesize + sp->v * sizeof *gsp); if (++sp->v >= sp->perpage) { if (++sp->u >= sp->pages) return (NULL); else sp->v = 0; } return (gsp); } diff --git a/lib/libgeom/geom_xml2tree.c b/lib/libgeom/geom_xml2tree.c index 5f4636f9368b..824800070933 100644 --- a/lib/libgeom/geom_xml2tree.c +++ b/lib/libgeom/geom_xml2tree.c @@ -1,533 +1,533 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-3-Clause-FreeBSD * * Copyright (c) 2003 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct mystate { struct gmesh *mesh; struct gclass *class; struct ggeom *geom; struct gprovider *provider; struct gconsumer *consumer; int level; struct sbuf *sbuf[20]; struct gconf *config; int nident; XML_Parser parser; int error; }; static void StartElement(void *userData, const char *name, const char **attr) { struct mystate *mt; void *id; void *ref; int i; mt = userData; mt->level++; mt->sbuf[mt->level] = sbuf_new_auto(); id = NULL; ref = NULL; for (i = 0; attr[i] != NULL; i += 2) { if (!strcmp(attr[i], "id")) { id = (void *)strtoul(attr[i + 1], NULL, 0); mt->nident++; } else if (!strcmp(attr[i], "ref")) { ref = (void *)strtoul(attr[i + 1], NULL, 0); } else printf("%*.*s[%s = %s]\n", mt->level + 1, mt->level + 1, "", attr[i], attr[i + 1]); } if (!strcmp(name, "class") && mt->class == NULL) { mt->class = calloc(1, sizeof *mt->class); if (mt->class == NULL) { mt->error = errno; XML_StopParser(mt->parser, 0); warn("Cannot allocate memory during processing of '%s' " "element", name); return; } mt->class->lg_id = id; LIST_INSERT_HEAD(&mt->mesh->lg_class, mt->class, lg_class); LIST_INIT(&mt->class->lg_geom); LIST_INIT(&mt->class->lg_config); return; } if (!strcmp(name, "geom") && mt->geom == NULL) { mt->geom = calloc(1, sizeof *mt->geom); if (mt->geom == NULL) { mt->error = errno; XML_StopParser(mt->parser, 0); warn("Cannot allocate memory during processing of '%s' " "element", name); return; } mt->geom->lg_id = id; LIST_INSERT_HEAD(&mt->class->lg_geom, mt->geom, lg_geom); LIST_INIT(&mt->geom->lg_provider); LIST_INIT(&mt->geom->lg_consumer); LIST_INIT(&mt->geom->lg_config); return; } if (!strcmp(name, "class") && mt->geom != NULL) { mt->geom->lg_class = ref; return; } if (!strcmp(name, "consumer") && mt->consumer == NULL) { mt->consumer = calloc(1, sizeof *mt->consumer); if (mt->consumer == NULL) { mt->error = errno; XML_StopParser(mt->parser, 0); warn("Cannot allocate memory during processing of '%s' " "element", name); return; } mt->consumer->lg_id = id; LIST_INSERT_HEAD(&mt->geom->lg_consumer, mt->consumer, lg_consumer); LIST_INIT(&mt->consumer->lg_config); return; } if (!strcmp(name, "geom") && mt->consumer != NULL) { mt->consumer->lg_geom = ref; return; } if (!strcmp(name, "provider") && mt->consumer != NULL) { mt->consumer->lg_provider = ref; return; } if (!strcmp(name, "provider") && mt->provider == NULL) { mt->provider = calloc(1, sizeof *mt->provider); if (mt->provider == NULL) { mt->error = errno; XML_StopParser(mt->parser, 0); warn("Cannot allocate memory during processing of '%s' " "element", name); return; } mt->provider->lg_id = id; LIST_INSERT_HEAD(&mt->geom->lg_provider, mt->provider, lg_provider); LIST_INIT(&mt->provider->lg_consumers); LIST_INIT(&mt->provider->lg_config); return; } if (!strcmp(name, "geom") && mt->provider != NULL) { mt->provider->lg_geom = ref; return; } if (!strcmp(name, "config")) { if (mt->provider != NULL) { mt->config = &mt->provider->lg_config; return; } if (mt->consumer != NULL) { mt->config = &mt->consumer->lg_config; return; } if (mt->geom != NULL) { mt->config = &mt->geom->lg_config; return; } if (mt->class != NULL) { mt->config = &mt->class->lg_config; return; } } } static void EndElement(void *userData, const char *name) { struct mystate *mt; struct gconf *c; struct gconfig *gc; char *p; mt = userData; p = NULL; if (sbuf_finish(mt->sbuf[mt->level]) == 0) p = strdup(sbuf_data(mt->sbuf[mt->level])); sbuf_delete(mt->sbuf[mt->level]); mt->sbuf[mt->level] = NULL; mt->level--; if (p == NULL) { mt->error = errno; XML_StopParser(mt->parser, 0); warn("Cannot allocate memory during processing of '%s' " "element", name); return; } if (strlen(p) == 0) { free(p); p = NULL; } if (!strcmp(name, "name")) { if (mt->provider != NULL) { mt->provider->lg_name = p; return; } else if (mt->geom != NULL) { mt->geom->lg_name = p; return; } else if (mt->class != NULL) { mt->class->lg_name = p; return; } } if (!strcmp(name, "rank") && mt->geom != NULL) { mt->geom->lg_rank = strtoul(p, NULL, 0); free(p); return; } if (!strcmp(name, "mode") && mt->provider != NULL) { mt->provider->lg_mode = p; return; } if (!strcmp(name, "mode") && mt->consumer != NULL) { mt->consumer->lg_mode = p; return; } if (!strcmp(name, "mediasize") && mt->provider != NULL) { mt->provider->lg_mediasize = strtoumax(p, NULL, 0); free(p); return; } if (!strcmp(name, "sectorsize") && mt->provider != NULL) { mt->provider->lg_sectorsize = strtoul(p, NULL, 0); free(p); return; } if (!strcmp(name, "stripesize") && mt->provider != NULL) { mt->provider->lg_stripesize = strtoumax(p, NULL, 0); free(p); return; } if (!strcmp(name, "stripeoffset") && mt->provider != NULL) { mt->provider->lg_stripeoffset = strtoumax(p, NULL, 0); free(p); return; } if (!strcmp(name, "config")) { mt->config = NULL; free(p); return; } if (mt->config != NULL || (!strcmp(name, "wither") && (mt->provider != NULL || mt->geom != NULL))) { if (mt->config != NULL) c = mt->config; else if (mt->provider != NULL) c = &mt->provider->lg_config; else c = &mt->geom->lg_config; gc = calloc(1, sizeof *gc); if (gc == NULL) { mt->error = errno; XML_StopParser(mt->parser, 0); warn("Cannot allocate memory during processing of '%s' " "element", name); free(p); return; } gc->lg_name = strdup(name); if (gc->lg_name == NULL) { mt->error = errno; XML_StopParser(mt->parser, 0); warn("Cannot allocate memory during processing of '%s' " "element", name); free(gc); free(p); return; } gc->lg_val = p; LIST_INSERT_HEAD(c, gc, lg_config); return; } if (p != NULL) { #if DEBUG_LIBGEOM > 0 printf("Unexpected XML: name=%s data=\"%s\"\n", name, p); #endif free(p); } if (!strcmp(name, "consumer") && mt->consumer != NULL) { mt->consumer = NULL; return; } if (!strcmp(name, "provider") && mt->provider != NULL) { mt->provider = NULL; return; } if (!strcmp(name, "geom") && mt->consumer != NULL) { return; } if (!strcmp(name, "geom") && mt->provider != NULL) { return; } if (!strcmp(name, "geom") && mt->geom != NULL) { mt->geom = NULL; return; } if (!strcmp(name, "class") && mt->geom != NULL) { return; } if (!strcmp(name, "class") && mt->class != NULL) { mt->class = NULL; return; } } static void CharData(void *userData , const XML_Char *s , int len) { struct mystate *mt; const char *b, *e; mt = userData; b = s; e = s + len - 1; while (isspace(*b) && b < e) b++; while (isspace(*e) && e > b) e--; if (e != b || (*b && !isspace(*b))) sbuf_bcat(mt->sbuf[mt->level], b, e - b + 1); } struct gident * geom_lookupid(struct gmesh *gmp, const void *id) { struct gident *gip; for (gip = gmp->lg_ident; gip->lg_id != NULL; gip++) if (gip->lg_id == id) return (gip); return (NULL); } int geom_xml2tree(struct gmesh *gmp, char *p) { XML_Parser parser; struct mystate *mt; struct gclass *cl; struct ggeom *ge; struct gprovider *pr; struct gconsumer *co; int error, i; memset(gmp, 0, sizeof *gmp); LIST_INIT(&gmp->lg_class); parser = XML_ParserCreate(NULL); if (parser == NULL) return (ENOMEM); mt = calloc(1, sizeof *mt); if (mt == NULL) { XML_ParserFree(parser); return (ENOMEM); } mt->mesh = gmp; mt->parser = parser; error = 0; XML_SetUserData(parser, mt); XML_SetElementHandler(parser, StartElement, EndElement); XML_SetCharacterDataHandler(parser, CharData); i = XML_Parse(parser, p, strlen(p), 1); if (mt->error != 0) error = mt->error; else if (i != 1) { error = XML_GetErrorCode(parser) == XML_ERROR_NO_MEMORY ? ENOMEM : EILSEQ; } XML_ParserFree(parser); if (error != 0) { free(mt); return (error); } gmp->lg_ident = calloc(sizeof *gmp->lg_ident, mt->nident + 1); free(mt); if (gmp->lg_ident == NULL) return (ENOMEM); i = 0; /* Collect all identifiers */ LIST_FOREACH(cl, &gmp->lg_class, lg_class) { gmp->lg_ident[i].lg_id = cl->lg_id; gmp->lg_ident[i].lg_ptr = cl; gmp->lg_ident[i].lg_what = ISCLASS; i++; LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { gmp->lg_ident[i].lg_id = ge->lg_id; gmp->lg_ident[i].lg_ptr = ge; gmp->lg_ident[i].lg_what = ISGEOM; i++; LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { gmp->lg_ident[i].lg_id = pr->lg_id; gmp->lg_ident[i].lg_ptr = pr; gmp->lg_ident[i].lg_what = ISPROVIDER; i++; } LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { gmp->lg_ident[i].lg_id = co->lg_id; gmp->lg_ident[i].lg_ptr = co; gmp->lg_ident[i].lg_what = ISCONSUMER; i++; } } } /* Substitute all identifiers */ LIST_FOREACH(cl, &gmp->lg_class, lg_class) { LIST_FOREACH(ge, &cl->lg_geom, lg_geom) { ge->lg_class = geom_lookupid(gmp, ge->lg_class)->lg_ptr; LIST_FOREACH(pr, &ge->lg_provider, lg_provider) { pr->lg_geom = geom_lookupid(gmp, pr->lg_geom)->lg_ptr; } LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) { co->lg_geom = geom_lookupid(gmp, co->lg_geom)->lg_ptr; if (co->lg_provider != NULL) { co->lg_provider = geom_lookupid(gmp, co->lg_provider)->lg_ptr; LIST_INSERT_HEAD( &co->lg_provider->lg_consumers, co, lg_consumers); } } } } return (0); } int geom_gettree(struct gmesh *gmp) { char *p; int error; p = geom_getxml(); if (p == NULL) return (errno); error = geom_xml2tree(gmp, p); free(p); return (error); } static void delete_config(struct gconf *gp) { struct gconfig *cf; for (;;) { cf = LIST_FIRST(gp); if (cf == NULL) return; LIST_REMOVE(cf, lg_config); free(cf->lg_name); free(cf->lg_val); free(cf); } } void geom_deletetree(struct gmesh *gmp) { struct gclass *cl; struct ggeom *ge; struct gprovider *pr; struct gconsumer *co; free(gmp->lg_ident); gmp->lg_ident = NULL; for (;;) { cl = LIST_FIRST(&gmp->lg_class); if (cl == NULL) break; LIST_REMOVE(cl, lg_class); delete_config(&cl->lg_config); if (cl->lg_name) free(cl->lg_name); for (;;) { ge = LIST_FIRST(&cl->lg_geom); if (ge == NULL) break; LIST_REMOVE(ge, lg_geom); delete_config(&ge->lg_config); if (ge->lg_name) free(ge->lg_name); for (;;) { pr = LIST_FIRST(&ge->lg_provider); if (pr == NULL) break; LIST_REMOVE(pr, lg_provider); delete_config(&pr->lg_config); if (pr->lg_name) free(pr->lg_name); if (pr->lg_mode) free(pr->lg_mode); free(pr); } for (;;) { co = LIST_FIRST(&ge->lg_consumer); if (co == NULL) break; LIST_REMOVE(co, lg_consumer); delete_config(&co->lg_config); if (co->lg_mode) free(co->lg_mode); free(co); } free(ge); } free(cl); } } diff --git a/lib/libgeom/libgeom.h b/lib/libgeom/libgeom.h index 075d2d21f26c..fc593b234302 100644 --- a/lib/libgeom/libgeom.h +++ b/lib/libgeom/libgeom.h @@ -1,172 +1,172 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-3-Clause-FreeBSD * * Copyright (c) 2003 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _LIBGEOM_H_ #define _LIBGEOM_H_ #include #include #include #include __BEGIN_DECLS #ifndef DEBUG_LIBGEOM #define DEBUG_LIBGEOM 0 #endif void geom_stats_close(void); void geom_stats_resync(void); int geom_stats_open(void); void *geom_stats_snapshot_get(void); void geom_stats_snapshot_free(void *); void geom_stats_snapshot_timestamp(void *, struct timespec *); void geom_stats_snapshot_reset(void *); struct devstat *geom_stats_snapshot_next(void *); char *geom_getxml(void); /* geom_xml2tree.c */ /* * These structs are used to build the tree based on the XML. * they're named as the kernel variant without the first '_'. */ struct gclass; struct ggeom; struct gconsumer; struct gprovider; LIST_HEAD(gconf, gconfig); struct gident { void *lg_id; void *lg_ptr; enum { ISCLASS, ISGEOM, ISPROVIDER, ISCONSUMER } lg_what; }; struct gmesh { LIST_HEAD(, gclass) lg_class; struct gident *lg_ident; }; struct gconfig { LIST_ENTRY(gconfig) lg_config; char *lg_name; char *lg_val; }; struct gclass { void *lg_id; char *lg_name; LIST_ENTRY(gclass) lg_class; LIST_HEAD(, ggeom) lg_geom; struct gconf lg_config; }; struct ggeom { void *lg_id; struct gclass *lg_class; char *lg_name; u_int lg_rank; LIST_ENTRY(ggeom) lg_geom; LIST_HEAD(, gconsumer) lg_consumer; LIST_HEAD(, gprovider) lg_provider; struct gconf lg_config; }; struct gconsumer { void *lg_id; struct ggeom *lg_geom; LIST_ENTRY(gconsumer) lg_consumer; struct gprovider *lg_provider; LIST_ENTRY(gconsumer) lg_consumers; char *lg_mode; struct gconf lg_config; }; struct gprovider { void *lg_id; char *lg_name; struct ggeom *lg_geom; LIST_ENTRY(gprovider) lg_provider; LIST_HEAD(, gconsumer) lg_consumers; char *lg_mode; off_t lg_mediasize; u_int lg_sectorsize; off_t lg_stripeoffset; off_t lg_stripesize; struct gconf lg_config; }; struct gident * geom_lookupid(struct gmesh *, const void *); int geom_xml2tree(struct gmesh *, char *); int geom_gettree(struct gmesh *); void geom_deletetree(struct gmesh *); /* geom_ctl.c */ struct gctl_req; #ifdef _STDIO_H_ /* limit #include pollution */ void gctl_dump(struct gctl_req *, FILE *); #endif void gctl_free(struct gctl_req *); struct gctl_req *gctl_get_handle(void); const char *gctl_issue(struct gctl_req *); void gctl_ro_param(struct gctl_req *, const char *, int, const void *); void gctl_rw_param(struct gctl_req *, const char *, int, void *); /* geom_util.c */ int g_open(const char *, int); int g_close(int); off_t g_mediasize(int); ssize_t g_sectorsize(int); off_t g_stripeoffset(int); off_t g_stripesize(int); int g_flush(int); int g_delete(int, off_t, off_t); int g_get_ident(int, char *, size_t); int g_get_name(const char *, char *, size_t); int g_open_by_ident(const char *, int, char *, size_t); char *g_device_path(const char *); char *g_providername(int); __END_DECLS #endif /* _LIBGEOM_H_ */ diff --git a/sbin/fsck_ffs/ea.c b/sbin/fsck_ffs/ea.c index 7cf20196dfae..54353005bdc0 100644 --- a/sbin/fsck_ffs/ea.c +++ b/sbin/fsck_ffs/ea.c @@ -1,88 +1,88 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-3-Clause-FreeBSD * * Copyright (c) 2002 Poul-Henning Kamp * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by Poul-Henning Kamp * and NAI Labs, the Security Research Division of Network Associates, Inc. * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the * DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "fsck.h" /* * Scan each entry in an ea block. */ int eascan(struct inodesc *idesc, struct ufs2_dinode *dp) { #if 1 return (0); #else struct bufarea *bp; u_int dsize, n; u_char *cp; long blksiz; char dbuf[DIRBLKSIZ]; printf("Inode %ju extsize %ju\n", (intmax_t)idesc->id_number, (uintmax_t)dp->di_extsize); if (dp->di_extsize == 0) return 0; if (dp->di_extsize <= sblock.fs_fsize) blksiz = sblock.fs_fsize; else blksiz = sblock.fs_bsize; printf("blksiz = %ju\n", (intmax_t)blksiz); bp = getdatablk(dp->di_extb[0], blksiz, BT_EXTATTR); cp = (u_char *)bp->b_un.b_buf; for (n = 0; n < blksiz; n++) { printf("%02x", cp[n]); if ((n & 31) == 31) printf("\n"); } brelse(bp); return (STOP); #endif } diff --git a/usr.sbin/gstat/gstat.c b/usr.sbin/gstat/gstat.c index c2d28720205f..65388c3002ff 100644 --- a/usr.sbin/gstat/gstat.c +++ b/usr.sbin/gstat/gstat.c @@ -1,603 +1,603 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-3-Clause-FreeBSD * * Copyright (c) 2003 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int flag_a, flag_b, flag_B, flag_c, flag_C, flag_d, flag_o, flag_p, flag_s; static int flag_I = 1000000; #define HIGH_PCT_BUSY_THRESH 80 #define MEDIUM_PCT_BUSY_THRESH 50 #define PRINTMSG(...) do { \ if ((flag_b && !loop) || (flag_B)) \ printf(__VA_ARGS__); \ else if (!flag_b) \ printw(__VA_ARGS__); \ } while(0) static void usage(void); static const char* el_prompt(void) { return ("Filter: "); } int main(int argc, char **argv) { int error, i, quit; int curx, cury, maxx, maxy, line_len, loop, max_flen, head_printed; struct devstat *gsp, *gsq; void *sp, *sq; double dt; struct timespec tp, tq; struct gmesh gmp; struct gprovider *pp; struct gconsumer *cp; struct gident *gid; regex_t f_re, tmp_f_re; short cf, cb; char *p; char f_s[100], pf_s[100], tmp_f_s[100]; char ts[100], g_name[4096]; const char *line; long double ld[16]; uint64_t u64; EditLine *el; History *hist; HistEvent hist_ev; hist = NULL; el = NULL; maxx = -1; curx = -1; loop = 1; /* Turn on batch mode if output is not tty. */ if (!isatty(fileno(stdout))) flag_b = 1; f_s[0] = '\0'; while ((i = getopt(argc, argv, "abBdcCf:I:ops")) != -1) { switch (i) { case 'a': flag_a = 1; break; case 'b': flag_b = 1; break; case 'B': flag_B = 1; flag_b = 1; break; case 'c': flag_c = 1; break; case 'C': flag_C = 1; /* csv out implies repeating batch mode */ flag_b = 1; flag_B = 1; head_printed = 0; break; case 'd': flag_d = 1; break; case 'f': if (strlen(optarg) > sizeof(f_s) - 1) errx(EX_USAGE, "Filter string too long"); if (regcomp(&f_re, optarg, REG_EXTENDED) != 0) errx(EX_USAGE, "Invalid filter - see re_format(7)"); strlcpy(f_s, optarg, sizeof(f_s)); break; case 'o': flag_o = 1; break; case 'I': p = NULL; i = strtoul(optarg, &p, 0); if (p == optarg || errno == EINVAL || errno == ERANGE) { errx(1, "Invalid argument to -I"); } else if (!strcmp(p, "s")) i *= 1000000; else if (!strcmp(p, "ms")) i *= 1000; else if (!strcmp(p, "us")) i *= 1; flag_I = i; break; case 'p': flag_p = 1; break; case 's': flag_s = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc != 0) usage(); i = geom_gettree(&gmp); if (i != 0) err(1, "geom_gettree = %d", i); error = geom_stats_open(); if (error) err(1, "geom_stats_open()"); sq = NULL; sq = geom_stats_snapshot_get(); if (sq == NULL) err(1, "geom_stats_snapshot()"); if (!flag_b) { /* Setup libedit */ hist = history_init(); if (hist == NULL) err(EX_SOFTWARE, "history_init()"); history(hist, &hist_ev, H_SETSIZE, 100); el = el_init("gstat", stdin, stdout, stderr); if (el == NULL) err(EX_SOFTWARE, "el_init"); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_SIGNAL, 1); el_set(el, EL_HIST, history, hist); el_set(el, EL_PROMPT, el_prompt); if (f_s[0] != '\0') history(hist, &hist_ev, H_ENTER, f_s); /* Setup curses */ initscr(); start_color(); use_default_colors(); pair_content(0, &cf, &cb); init_pair(1, COLOR_GREEN, cb); init_pair(2, COLOR_MAGENTA, cb); init_pair(3, COLOR_RED, cb); cbreak(); noecho(); nonl(); nodelay(stdscr, 1); intrflush(stdscr, FALSE); keypad(stdscr, TRUE); } geom_stats_snapshot_timestamp(sq, &tq); for (quit = 0; !quit;) { sp = geom_stats_snapshot_get(); if (sp == NULL) err(1, "geom_stats_snapshot()"); geom_stats_snapshot_timestamp(sp, &tp); dt = tp.tv_sec - tq.tv_sec; dt += (tp.tv_nsec - tq.tv_nsec) * 1e-9; tq = tp; if (flag_C) { /* set timestamp string */ (void)strftime(ts,sizeof(ts), "%F %T",localtime(&tq.tv_sec)); (void)snprintf(ts,sizeof(ts), "%s.%.9ld",ts,tq.tv_nsec); } geom_stats_snapshot_reset(sp); geom_stats_snapshot_reset(sq); if (!flag_b) move(0,0); if (!flag_C) PRINTMSG("dT: %5.3fs w: %.3fs", dt, (float)flag_I / 1000000); if (!flag_C && f_s[0] != '\0') { PRINTMSG(" filter: "); if (!flag_b) { getyx(stdscr, cury, curx); getmaxyx(stdscr, maxy, maxx); } strlcpy(pf_s, f_s, sizeof(pf_s)); max_flen = maxx - curx - 1; if ((int)strlen(f_s) > max_flen && max_flen >= 0) { if (max_flen > 3) pf_s[max_flen - 3] = '.'; if (max_flen > 2) pf_s[max_flen - 2] = '.'; if (max_flen > 1) pf_s[max_flen - 1] = '.'; pf_s[max_flen] = '\0'; } PRINTMSG("%s", pf_s); } if (!flag_C) { PRINTMSG("\n"); PRINTMSG(" L(q) ops/s "); if (flag_s) { PRINTMSG(" r/s kB kBps ms/r "); PRINTMSG(" w/s kB kBps ms/w "); } else { PRINTMSG(" r/s kBps ms/r "); PRINTMSG(" w/s kBps ms/w "); } if (flag_d) { if (flag_s) { PRINTMSG(" d/s kB kBps"); PRINTMSG(" ms/d "); } else PRINTMSG(" d/s kBps ms/d "); } if (flag_o) PRINTMSG(" o/s ms/o "); PRINTMSG("%%busy Name\n"); } else if (flag_C && !head_printed) { PRINTMSG("timestamp,name,q-depth,total_ops/s"); if (flag_s) { PRINTMSG(",read/s,read_sz-KiB"); PRINTMSG(",read-KiB/s,ms/read"); PRINTMSG(",write/s,write_sz-KiB"); PRINTMSG(",write-KiB/s,ms/write"); } else { PRINTMSG(",read/s,read-KiB/s,ms/read"); PRINTMSG(",write/s,write-KiB/s,ms/write"); } if (flag_d) { if (flag_s) { PRINTMSG(",delete/s,delete-sz-KiB"); PRINTMSG(",delete-KiB/s,ms/delete"); } else { PRINTMSG(",delete/s,delete-KiB/s"); PRINTMSG(",ms/delete"); } } if (flag_o) PRINTMSG(",other/s,ms/other"); PRINTMSG(",%%busy\n"); head_printed = 1; } for (;;) { gsp = geom_stats_snapshot_next(sp); gsq = geom_stats_snapshot_next(sq); if (gsp == NULL || gsq == NULL) break; if (gsp->id == NULL) continue; gid = geom_lookupid(&gmp, gsp->id); if (gid == NULL) { geom_deletetree(&gmp); i = geom_gettree(&gmp); if (i != 0) err(1, "geom_gettree = %d", i); gid = geom_lookupid(&gmp, gsp->id); } if (gid == NULL) continue; if (gid->lg_what == ISCONSUMER && !flag_c) continue; if (flag_p && gid->lg_what == ISPROVIDER && ((struct gprovider *) (gid->lg_ptr))->lg_geom->lg_rank != 1) continue; /* Do not print past end of window */ if (!flag_b) { getyx(stdscr, cury, curx); if (curx > 0) continue; } if ((gid->lg_what == ISPROVIDER || gid->lg_what == ISCONSUMER) && f_s[0] != '\0') { pp = gid->lg_ptr; if ((regexec(&f_re, pp->lg_name, 0, NULL, 0) != 0)) continue; } if (gsp->sequence0 != gsp->sequence1) { /* * it is ok to skip entire line silently * for CSV output */ if (!flag_C) PRINTMSG("*\n"); continue; } devstat_compute_statistics(gsp, gsq, dt, DSM_QUEUE_LENGTH, &u64, DSM_TRANSFERS_PER_SECOND, &ld[0], DSM_TRANSFERS_PER_SECOND_READ, &ld[1], DSM_MB_PER_SECOND_READ, &ld[2], DSM_MS_PER_TRANSACTION_READ, &ld[3], DSM_TRANSFERS_PER_SECOND_WRITE, &ld[4], DSM_MB_PER_SECOND_WRITE, &ld[5], DSM_MS_PER_TRANSACTION_WRITE, &ld[6], DSM_BUSY_PCT, &ld[7], DSM_TRANSFERS_PER_SECOND_FREE, &ld[8], DSM_MB_PER_SECOND_FREE, &ld[9], DSM_MS_PER_TRANSACTION_FREE, &ld[10], DSM_TRANSFERS_PER_SECOND_OTHER, &ld[11], DSM_MS_PER_TRANSACTION_OTHER, &ld[12], DSM_KB_PER_TRANSFER_READ, &ld[13], DSM_KB_PER_TRANSFER_WRITE, &ld[14], DSM_KB_PER_TRANSFER_FREE, &ld[15], DSM_NONE); if (flag_a && ld[7] < 0.1) { *gsq = *gsp; continue; } /* store name for geom device */ if (gid == NULL) { (void)snprintf(g_name, sizeof(g_name), "??"); } else if (gid->lg_what == ISPROVIDER) { pp = gid->lg_ptr; (void)snprintf(g_name, sizeof(g_name), "%s", pp->lg_name); } else if (gid->lg_what == ISCONSUMER) { cp = gid->lg_ptr; (void)snprintf(g_name, sizeof(g_name), "%s/%s/%s", cp->lg_geom->lg_class->lg_name, cp->lg_geom->lg_name, cp->lg_provider->lg_name); } if (flag_C) { PRINTMSG("%s", ts); /* timestamp */ PRINTMSG(",%s", g_name); /* print name */ PRINTMSG(",%ju", (uintmax_t)u64); PRINTMSG(",%.0f", (double)ld[0]); PRINTMSG(",%.0f", (double)ld[1]); if (flag_s) PRINTMSG(",%.0f", (double)ld[13]); PRINTMSG(",%.0f", (double)ld[2] * 1024); if (ld[3] > 1e3) PRINTMSG(",%.0f", (double)ld[3]); else PRINTMSG(",%.1f", (double)ld[3]); PRINTMSG(",%.0f", (double)ld[4]); if (flag_s) PRINTMSG(",%.0f", (double)ld[14]); PRINTMSG(",%.0f", (double)ld[5] * 1024); if (ld[6] > 1e3) PRINTMSG(",%.0f", (double)ld[6]); else PRINTMSG(",%.1f", (double)ld[6]); if (flag_d) { PRINTMSG(",%.0f", (double)ld[8]); if (flag_s) PRINTMSG(",%.0f", (double)ld[15]); PRINTMSG(",%.0f", (double)ld[9] * 1024); if (ld[10] > 1e3) PRINTMSG(",%.0f", (double)ld[10]); else PRINTMSG(",%.1f", (double)ld[10]); } if (flag_o) { PRINTMSG(",%.0f", (double)ld[11]); if (ld[12] > 1e3) PRINTMSG(",%.0f", (double)ld[12]); else PRINTMSG(",%.1f", (double)ld[12]); } PRINTMSG(",%.1lf", (double)ld[7]); } else { PRINTMSG(" %4ju", (uintmax_t)u64); PRINTMSG(" %6.0f", (double)ld[0]); PRINTMSG(" %6.0f", (double)ld[1]); if (flag_s) PRINTMSG(" %6.0f", (double)ld[13]); PRINTMSG(" %6.0f", (double)ld[2] * 1024); if (ld[3] > 1e3) PRINTMSG(" %6.0f", (double)ld[3]); else PRINTMSG(" %6.1f", (double)ld[3]); PRINTMSG(" %6.0f", (double)ld[4]); if (flag_s) PRINTMSG(" %6.0f", (double)ld[14]); PRINTMSG(" %6.0f", (double)ld[5] * 1024); if (ld[6] > 1e3) PRINTMSG(" %6.0f", (double)ld[6]); else PRINTMSG(" %6.1f", (double)ld[6]); if (flag_d) { PRINTMSG(" %6.0f", (double)ld[8]); if (flag_s) PRINTMSG(" %6.0f", (double)ld[15]); PRINTMSG(" %6.0f", (double)ld[9] * 1024); if (ld[10] > 1e3) PRINTMSG(" %6.0f", (double)ld[10]); else PRINTMSG(" %6.1f", (double)ld[10]); } if (flag_o) { PRINTMSG(" %6.0f", (double)ld[11]); if (ld[12] > 1e3) PRINTMSG(" %6.0f", (double)ld[12]); else PRINTMSG(" %6.1f", (double)ld[12]); } if (ld[7] > HIGH_PCT_BUSY_THRESH) i = 3; else if (ld[7] > MEDIUM_PCT_BUSY_THRESH) i = 2; else i = 1; if (!flag_b) attron(COLOR_PAIR(i)); PRINTMSG(" %6.1lf", (double)ld[7]); if (!flag_b) { attroff(COLOR_PAIR(i)); PRINTMSG("|"); } else PRINTMSG(" "); PRINTMSG(" %s", g_name); if (!flag_b) clrtoeol(); } PRINTMSG("\n"); *gsq = *gsp; } geom_stats_snapshot_free(sp); if (flag_b) { /* We loop extra to make sure we get the information. */ if (!loop) break; if (!flag_B) loop = 0; else if (fflush(stdout) == EOF) goto out; usleep(flag_I); continue; } getyx(stdscr, cury, curx); getmaxyx(stdscr, maxy, maxx); clrtobot(); if (maxy - 1 <= cury) move(maxy - 1, 0); refresh(); usleep(flag_I); while((i = getch()) != ERR) { switch (i) { case '>': flag_I *= 2; break; case '<': flag_I /= 2; if (flag_I < 1000) flag_I = 1000; break; case 'c': flag_c = !flag_c; break; case 'f': move(0,0); clrtoeol(); refresh(); line = el_gets(el, &line_len); if (line == NULL) err(1, "el_gets"); if (line_len > 1) history(hist, &hist_ev, H_ENTER, line); strlcpy(tmp_f_s, line, sizeof(f_s)); if ((p = strchr(tmp_f_s, '\n')) != NULL) *p = '\0'; /* * Fix the terminal. We messed up * curses idea of the screen by using * libedit. */ clear(); refresh(); cbreak(); noecho(); nonl(); if (regcomp(&tmp_f_re, tmp_f_s, REG_EXTENDED) != 0) { move(0, 0); printw("Invalid filter"); refresh(); sleep(1); } else { strlcpy(f_s, tmp_f_s, sizeof(f_s)); f_re = tmp_f_re; } break; case 'F': f_s[0] = '\0'; break; case 'q': quit = 1; break; default: break; } } } out: if (!flag_b) { el_end(el); endwin(); } exit(EX_OK); } static void usage(void) { fprintf(stderr, "usage: gstat [-abBcCdps] [-f filter] [-I interval]\n"); exit(EX_USAGE); /* NOTREACHED */ }