Date: Thu, 27 Feb 2014 00:43:10 +0000 (UTC) From: Eitan Adler <eadler@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r262539 - in head: sys/compat/linprocfs usr.bin/makewhatis Message-ID: <201402270043.s1R0hAU9098502@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: eadler Date: Thu Feb 27 00:43:10 2014 New Revision: 262539 URL: http://svnweb.freebsd.org/changeset/base/262539 Log: linprocfs: add support for /sys/kernel/random/uuid PR: kern/186187 Submitted by: Fernando <fernando.apesteguia@gmail.com> MFC After: 2 weeks Modified: head/sys/compat/linprocfs/linprocfs.c head/usr.bin/makewhatis/makewhatis.1 head/usr.bin/makewhatis/makewhatis.c Modified: head/sys/compat/linprocfs/linprocfs.c ============================================================================== --- head/sys/compat/linprocfs/linprocfs.c Wed Feb 26 23:03:10 2014 (r262538) +++ head/sys/compat/linprocfs/linprocfs.c Thu Feb 27 00:43:10 2014 (r262539) @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$"); #include <sys/time.h> #include <sys/tty.h> #include <sys/user.h> +#include <sys/uuid.h> #include <sys/vmmeter.h> #include <sys/vnode.h> #include <sys/bus.h> @@ -1337,6 +1338,22 @@ linprocfs_dofdescfs(PFS_FILL_ARGS) return (0); } + +/* + * Filler function for proc/sys/kernel/random/uuid + */ +static int +linprocfs_douuid(PFS_FILL_ARGS) +{ + struct uuid uuid; + + kern_uuidgen(&uuid, 1); + sbuf_printf_uuid(sb, &uuid); + sbuf_printf(sb, "\n"); + return(0); +} + + /* * Constructor */ @@ -1436,6 +1453,11 @@ linprocfs_init(PFS_INIT_ARGS) pfs_create_file(dir, "sem", &linprocfs_dosem, NULL, NULL, NULL, PFS_RD); + /* /proc/sys/kernel/random/... */ + dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0); + pfs_create_file(dir, "uuid", &linprocfs_douuid, + NULL, NULL, NULL, PFS_RD); + return (0); } Modified: head/usr.bin/makewhatis/makewhatis.1 ============================================================================== --- head/usr.bin/makewhatis/makewhatis.1 Wed Feb 26 23:03:10 2014 (r262538) +++ head/usr.bin/makewhatis/makewhatis.1 Thu Feb 27 00:43:10 2014 (r262539) @@ -24,12 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd December 3, 2005 -.Dt MAKEWHATIS 1 +.Dd December 8, 2013 +.Dt MAKEWHATIS 8 .Os .Sh NAME .Nm makewhatis -.Nd "create whatis database" +.Nd create whatis database .Sh SYNOPSIS .Nm .Op Fl a @@ -98,9 +98,6 @@ option is used. .It Ev MACHINE If set, its value is used to override the current machine type when searching machine specific subdirectories. -.It Ev MACHINE_ARCH -If set, its value is used to override the current -architecture when searching architecture specific subdirectories. .It Ev MANPATH Determines the set of directories to be processed if none are given on the command line. @@ -133,4 +130,6 @@ program was originally written in Perl a The current version of .Nm was rewritten in C by -.An John Rochester . +.An John Rochester +with additional contributions by +.An Franco Fichtner Aq Mt franco@lastsummer.de . Modified: head/usr.bin/makewhatis/makewhatis.c ============================================================================== --- head/usr.bin/makewhatis/makewhatis.c Wed Feb 26 23:03:10 2014 (r262538) +++ head/usr.bin/makewhatis/makewhatis.c Thu Feb 27 00:43:10 2014 (r262539) @@ -1,5 +1,6 @@ /*- * Copyright (c) 2002 John Rochester + * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,21 +25,19 @@ * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - +#include <sys/tree.h> #include <sys/types.h> -#include <sys/stat.h> #include <sys/param.h> #include <sys/queue.h> -#include <sys/utsname.h> +#include <sys/stat.h> #include <ctype.h> #include <dirent.h> #include <err.h> -#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -52,16 +51,56 @@ __FBSDID("$FreeBSD$"); static char blank[] = ""; /* - * Information collected about each man page in a section. + * Information collected about each man page alias. + */ +struct page_alias { + RB_ENTRY(page_alias) entry; + char *filename; + char *name; + char *suffix; + int gzipped; +}; + +/* + * Information collected about each unique man page. */ struct page_info { - char * filename; - char * name; - char * suffix; - int gzipped; - ino_t inode; + RB_HEAD(page_alias_tree, page_alias) head; + RB_ENTRY(page_info) entry; + ino_t inode; }; +static RB_HEAD(page_info_tree, page_info) page_head = RB_INITIALIZER(&page_head); + +/* + * Sorts page info by inode number. + */ +static int +infosort(const struct page_info *a, const struct page_info *b) +{ + return (memcmp(&a->inode, &b->inode, sizeof(a->inode))); +} + +RB_PROTOTYPE(page_info_tree, page_info, entry, infosort); +RB_GENERATE(page_info_tree, page_info, entry, infosort); + +/* + * Sorts page alias first by suffix, then name. + */ +static int +aliassort(const struct page_alias *a, const struct page_alias *b) +{ + int ret = strcmp(a->suffix, b->suffix); + if (ret) { + return (ret); + } + + return (strcmp(a->name, b->name)); +} + +RB_PROTOTYPE(page_alias_tree, page_alias, entry, aliassort); +RB_GENERATE(page_alias_tree, page_alias, entry, aliassort); + /* * An entry kept for each visited directory. */ @@ -100,7 +139,7 @@ static const char *whatis_name="whatis"; static char *common_output; /* -o option: the single output file */ static char *locale; /* user's locale if -L is used */ static char *lang_locale; /* short form of locale */ -static const char *machine, *machine_arch; +static const char *machine; static int exit_code; /* exit code to use when finished */ static SLIST_HEAD(, visited_dir) visited_dirs = @@ -132,62 +171,66 @@ static char mdoc_commands[] = "ArDvErEvF static void free_page_info(struct page_info *info) { - free(info->filename); - free(info->name); - free(info->suffix); + struct page_alias *alias; + + while ((alias = RB_ROOT(&info->head))) { + RB_REMOVE(page_alias_tree, &info->head, alias); + free(alias->filename); + free(alias->suffix); + free(alias->name); + free(alias); + } + free(info); } /* - * Allocates and fills in a new struct page_info given the - * name of the man section directory and the dirent of the file. - * If the file is not a man page, returns NULL. + * Allocates and fills in a new struct page_alias given the + * full file name of the man page and its dirent. + * If the file is not a man page, nothing is added. */ -static struct page_info * -new_page_info(char *dir, struct dirent *dirent) +static void +new_page_alias(struct page_info *info, char *filename, struct dirent *dirent) { - struct page_info *info; - int basename_length; + int gzipped, basename_length; + struct page_alias *alias; char *suffix; - struct stat st; - info = (struct page_info *) malloc(sizeof(struct page_info)); - if (info == NULL) - err(1, "malloc"); basename_length = strlen(dirent->d_name); suffix = &dirent->d_name[basename_length]; - asprintf(&info->filename, "%s/%s", dir, dirent->d_name); - if ((info->gzipped = basename_length >= 4 && strcmp(&dirent->d_name[basename_length - 3], ".gz") == 0)) { + + gzipped = basename_length >= 4 && + strcmp(&dirent->d_name[basename_length - 3], ".gz") == 0; + if (gzipped) { suffix -= 3; *suffix = '\0'; } + for (;;) { if (--suffix == dirent->d_name || !isalnum(*suffix)) { - if (*suffix == '.') + if (*suffix == '.') { break; - if (verbose) - warnx("%s: invalid man page name", info->filename); - free(info->filename); - free(info); - return NULL; + } + if (verbose) { + warnx("%s: invalid man page name", filename); + } + return; } } + *suffix++ = '\0'; - info->name = strdup(dirent->d_name); - info->suffix = strdup(suffix); - if (stat(info->filename, &st) < 0) { - warn("%s", info->filename); - free_page_info(info); - return NULL; - } - if (!S_ISREG(st.st_mode)) { - if (verbose && !S_ISDIR(st.st_mode)) - warnx("%s: not a regular file", info->filename); - free_page_info(info); - return NULL; + + alias = malloc(sizeof(*alias)); + if (alias == NULL) { + err(1, "malloc"); } - info->inode = st.st_ino; - return info; + + alias->name = strdup(dirent->d_name); /* XXX unsafe */ + alias->filename = strdup(filename); /* XXX unsafe */ + alias->suffix = strdup(suffix); /* XXX unsafe */ + alias->gzipped = gzipped; + + RB_INSERT(page_alias_tree, &info->head, alias); } /* @@ -206,10 +249,10 @@ static struct sbuf * new_sbuf(void) { struct sbuf *sbuf = (struct sbuf *) malloc(sizeof(struct sbuf)); - sbuf->content = (char *) malloc(LINE_ALLOC); + sbuf->content = malloc(LINE_ALLOC); sbuf->last = sbuf->content + LINE_ALLOC - 1; sbuf_clear(sbuf); - return sbuf; + return(sbuf); } /* @@ -227,7 +270,7 @@ sbuf_need(struct sbuf *sbuf, int nchars) size *= 2; cntsize = sbuf->end - sbuf->content; - new_content = (char *)malloc(size); + new_content = malloc(size); memcpy(new_content, sbuf->content, cntsize); free(sbuf->content); sbuf->content = new_content; @@ -288,29 +331,7 @@ static char * sbuf_content(struct sbuf *sbuf) { *sbuf->end = '\0'; - return sbuf->content; -} - -/* - * Returns true if no man page exists in the directory with - * any of the names in the StringList. - */ -static int -no_page_exists(char *dir, StringList *names, char *suffix) -{ - char path[MAXPATHLEN]; - size_t i; - - for (i = 0; i < names->sl_cur; i++) { - snprintf(path, sizeof path, "%s/%s.%s.gz", dir, names->sl_str[i], suffix); - if (access(path, F_OK) < 0) { - path[strlen(path) - 3] = '\0'; - if (access(path, F_OK) < 0) - continue; - } - return 0; - } - return 1; + return(sbuf->content); } static void @@ -337,7 +358,7 @@ open_output(char *name) if (output == NULL) { warn("%s", name); exit_code = 1; - return NULL; + return(NULL); } while (fgets(line, sizeof line, output) != NULL) { line[strlen(line) - 1] = '\0'; @@ -352,15 +373,15 @@ open_output(char *name) if (output == NULL) { warn("%s", name); exit_code = 1; - return NULL; + return(NULL); } - return output; + return(output); } static int linesort(const void *a, const void *b) { - return strcmp((*(const char * const *)a), (*(const char * const *)b)); + return(strcmp((*(const char * const *)a), (*(const char * const *)b))); } /* @@ -372,7 +393,8 @@ finish_output(FILE *output, char *name) size_t i; char *prev = NULL; - qsort(whatis_lines->sl_str, whatis_lines->sl_cur, sizeof(char *), linesort); + qsort(whatis_lines->sl_str, whatis_lines->sl_cur, sizeof(char *), + linesort); for (i = 0; i < whatis_lines->sl_cur; i++) { char *line = whatis_lines->sl_str[i]; if (i > 0 && strcmp(line, prev) == 0) @@ -395,7 +417,7 @@ open_whatis(char *mandir) char filename[MAXPATHLEN]; snprintf(filename, sizeof filename, "%s/%s", mandir, whatis_name); - return open_output(filename); + return(open_output(filename)); } static void @@ -419,20 +441,20 @@ already_visited(char *dir) if (stat(dir, &st) < 0) { warn("%s", dir); exit_code = 1; - return 1; + return(1); } SLIST_FOREACH(visit, &visited_dirs, next) { if (visit->inode == st.st_ino && visit->device == st.st_dev) { warnx("already visited %s", dir); - return 1; + return(1); } } visit = (struct visited_dir *) malloc(sizeof(struct visited_dir)); visit->device = st.st_dev; visit->inode = st.st_ino; SLIST_INSERT_HEAD(&visited_dirs, visit, next); - return 0; + return(0); } /* @@ -446,7 +468,7 @@ trim_rhs(char *str) while (--rhs > str && isspace(*rhs)) ; *++rhs = '\0'; - return rhs; + return(rhs); } /* @@ -457,7 +479,7 @@ skip_spaces(char *s) { while (*s != '\0' && isspace(*s)) s++; - return s; + return(s); } /* @@ -467,10 +489,10 @@ static int only_digits(char *line) { if (!isdigit(*line++)) - return 0; + return(0); while (isdigit(*line)) line++; - return *line == '\0'; + return(*line == '\0'); } /* @@ -487,7 +509,7 @@ name_section_line(char *line, const char const char **title; if (strncmp(line, section_start, 3) != 0) - return 0; + return(0); line = skip_spaces(line + 3); rhs = trim_rhs(line); if (*line == '"') { @@ -497,8 +519,8 @@ name_section_line(char *line, const char } for (title = name_section_titles; *title != NULL; title++) if (strcmp(*title, line) == 0) - return 1; - return 0; + return(1); + return(0); } /* @@ -518,7 +540,7 @@ de_nroff_copy(char *from, char *to, int switch (*++from) { case '(': if (strncmp(&from[1], "em", 2) == 0 || - strncmp(&from[1], "mi", 2) == 0) { + strncmp(&from[1], "mi", 2) == 0) { from += 3; continue; } @@ -534,7 +556,8 @@ de_nroff_copy(char *from, char *to, int if (*++from == '(') from += 3; else if (*from == '[') { - while (*++from != ']' && from < from_end); + while (*++from != ']' && from < from_end) + ; from++; } else from++; @@ -547,7 +570,7 @@ de_nroff_copy(char *from, char *to, int } *to++ = *from++; } - return to; + return(to); } /* @@ -594,6 +617,38 @@ process_man_line(char *line) } } +struct mdoc_text { + const char *mdoc; + const char *text; +}; + +static int +process_mdoc_macro(char *line) +{ + static const struct mdoc_text list[] = { + { ".At", "AT&T UNIX" }, + { ".Bsx", "BSD/OS" }, + { ".Bx", "BSD" }, + { ".Dx", "DragonFly" }, + { ".Fx", "FreeBSD" }, + { ".Nx", "NetBSD" }, + { ".Ox", "OpenBSD" }, + { ".Ux", "UNIX" }, + }; + unsigned int i; + + for (i = 0; i < sizeof(list) / sizeof(list[0]); ++i) { + if (!strcmp(line, list[i].mdoc)) { + sbuf_append(whatis_proto, list[i].text, + strlen(list[i].text)); + sbuf_append(whatis_proto, " ", 1); + return (1); + } + } + + return (0); +} + /* * Processes a new-style mdoc(7) line. */ @@ -613,6 +668,9 @@ process_mdoc_line(char *line) sbuf_append(whatis_proto, " ", 1); return; } + if (process_mdoc_macro(line)) { + return; + } xref = strncmp(line, ".Xr", 3) == 0; line += 3; while ((line = skip_spaces(line)) < line_end) { @@ -663,27 +721,6 @@ process_mdoc_line(char *line) sbuf_append(whatis_proto, " ", 1); } -/* - * Collects a list of comma-separated names from the text. - */ -static void -collect_names(StringList *names, char *text) -{ - char *arg; - - for (;;) { - arg = text; - text = strchr(text, ','); - if (text != NULL) - *text++ = '\0'; - sl_add(names, arg); - if (text == NULL) - return; - if (*text == ' ') - text++; - } -} - enum { STATE_UNKNOWN, STATE_MANSTYLE, STATE_MDOCNAME, STATE_MDOCDESC }; /* @@ -691,25 +728,33 @@ enum { STATE_UNKNOWN, STATE_MANSTYLE, ST * to whatis_lines. */ static void -process_page(struct page_info *page, char *section_dir) +process_page(struct page_info *info) { - gzFile in; - char buffer[4096]; - char *line; - StringList *names; - char *descr; int state = STATE_UNKNOWN; - size_t i; + struct page_alias *alias; + char *line, *descr; + char buffer[4096]; + gzFile in; + + /* + * Only read the page once for each inode. It's + * safe to assume that page->list is set. + */ + alias = RB_MIN(page_alias_tree, &info->head); + + if (verbose) { + fprintf(stderr, "\treading %s\n", alias->filename); + } sbuf_clear(whatis_proto); - if ((in = gzopen(page->filename, "r")) == NULL) { - warn("%s", page->filename); + if ((in = gzopen(alias->filename, "r")) == NULL) { + warn("%s", alias->filename); exit_code = 1; return; } - while (gzgets(in, buffer, sizeof buffer) != NULL) { + while (gzgets(in, buffer, sizeof(buffer)) != NULL) { line = buffer; - if (strncmp(line, ".\\\"", 3) == 0) /* ignore comments */ + if (strncmp(line, ".\\\"", 3) == 0) /* ignore comments */ continue; switch (state) { /* @@ -779,7 +824,9 @@ process_page(struct page_info *page, cha descr = strchr(line, ' '); if (descr == NULL) { if (verbose) - fprintf(stderr, " ignoring junk description \"%s\"\n", line); + fprintf(stderr, + "\tignoring junk description \"%s\"\n", + line); return; } *descr++ = '\0'; @@ -787,19 +834,16 @@ process_page(struct page_info *page, cha *descr = '\0'; descr += 3; } - names = sl_init(); - collect_names(names, line); sbuf_clear(whatis_final); - if (!sl_find(names, page->name) && no_page_exists(section_dir, names, page->suffix)) { + RB_FOREACH(alias, page_alias_tree, &info->head) { /* - * Add the page name since that's the only thing that - * man(1) will find. + * This won't append names stored in `line'. + * The reason for that is that we cannot be sure + * which section they belong to unless we have + * a real alias (via MLINKS) in this list. */ - add_whatis_name(page->name, page->suffix); + add_whatis_name(alias->name, alias->suffix); } - for (i = 0; i < names->sl_cur; i++) - add_whatis_name(names->sl_str[i], page->suffix); - sl_free(names, 0); sbuf_retract(whatis_final, 2); /* remove last ", " */ while (sbuf_length(whatis_final) < indent) sbuf_append(whatis_final, " ", 1); @@ -809,33 +853,19 @@ process_page(struct page_info *page, cha } /* - * Sorts pages first by inode number, then by name. - */ -static int -pagesort(const void *a, const void *b) -{ - const struct page_info *p1 = *(struct page_info * const *) a; - const struct page_info *p2 = *(struct page_info * const *) b; - if (p1->inode == p2->inode) - return strcmp(p1->name, p2->name); - return p1->inode - p2->inode; -} - -/* * Processes a single man section. */ static void process_section(char *section_dir) { struct dirent **entries; + struct page_info *info; int nentries; - struct page_info **pages; - int npages = 0; int i; - ino_t prev_inode = 0; - if (verbose) + if (verbose) { fprintf(stderr, " %s\n", section_dir); + } /* * scan the man section directory for pages @@ -846,33 +876,55 @@ process_section(char *section_dir) exit_code = 1; return; } + /* * collect information about man pages */ - pages = (struct page_info **) calloc(nentries, sizeof(struct page_info *)); for (i = 0; i < nentries; i++) { - struct page_info *info = new_page_info(section_dir, entries[i]); - if (info != NULL) - pages[npages++] = info; + struct page_info ref; + char *filename; + struct stat st; + + if (asprintf(&filename, "%s/%s", section_dir, + entries[i]->d_name) < 0) { + err(1, "malloc"); + } + + if (stat(filename, &st) < 0) { + warn("%s", filename); + goto process_section_next; + } + + if (!S_ISREG(st.st_mode)) { + if (verbose && !S_ISDIR(st.st_mode)) + warnx("%s: not a regular file", filename); + goto process_section_next; + } + + ref.inode = st.st_ino; + + info = RB_FIND(page_info_tree, &page_head, &ref); + if (info == NULL) { + info = malloc(sizeof(*info)); + if (info == NULL) { + err(1, "malloc"); + } + + bzero(info, sizeof(*info)); + info->inode = st.st_ino; + RB_INIT(&info->head); + + RB_INSERT(page_info_tree, &page_head, info); + } + + new_page_alias(info, filename, entries[i]); + +process_section_next: + free(entries[i]); + free(filename); } free(entries); - qsort(pages, npages, sizeof(struct page_info *), pagesort); - /* - * process each unique page - */ - for (i = 0; i < npages; i++) { - struct page_info *page = pages[i]; - if (page->inode != prev_inode) { - prev_inode = page->inode; - if (verbose) - fprintf(stderr, " reading %s\n", page->filename); - process_page(page, section_dir); - } else if (verbose) - fprintf(stderr, " skipping %s, duplicate\n", page->filename); - free_page_info(page); - } - free(pages); } /* @@ -884,12 +936,12 @@ select_sections(const struct dirent *ent const char *p = &entry->d_name[3]; if (strncmp(entry->d_name, "man", 3) != 0) - return 0; + return(0); while (*p != '\0') { if (!isalnum(*p++)) - return 0; + return(0); } - return 1; + return(1); } /* @@ -900,6 +952,7 @@ static void process_mandir(char *dir_name) { struct dirent **entries; + struct page_info *info; int nsections; FILE *fp = NULL; int i; @@ -919,21 +972,26 @@ process_mandir(char *dir_name) return; for (i = 0; i < nsections; i++) { char section_dir[MAXPATHLEN]; - snprintf(section_dir, sizeof section_dir, "%s/%s", dir_name, entries[i]->d_name); + snprintf(section_dir, sizeof section_dir, "%s/%s", dir_name, + entries[i]->d_name); process_section(section_dir); snprintf(section_dir, sizeof section_dir, "%s/%s/%s", dir_name, - entries[i]->d_name, machine); + entries[i]->d_name, machine); if (stat(section_dir, &st) == 0 && S_ISDIR(st.st_mode)) process_section(section_dir); - if (strcmp(machine_arch, machine) != 0) { - snprintf(section_dir, sizeof section_dir, "%s/%s/%s", - dir_name, entries[i]->d_name, machine_arch); - if (stat(section_dir, &st) == 0 && S_ISDIR(st.st_mode)) - process_section(section_dir); - } free(entries[i]); } free(entries); + + /* + * process and free all pages + */ + while ((info = RB_ROOT(&page_head))) { + RB_REMOVE(page_info_tree, &page_head, info); + process_page(info); + free_page_info(info); + } + if (common_output == NULL) finish_whatis(fp, dir_name); } @@ -1003,7 +1061,9 @@ main(int argc, char **argv) char *sep = strchr(locale, '_'); if (sep != NULL && isupper(sep[1]) && isupper(sep[2])) { - asprintf(&lang_locale, "%.*s%s", (int)(ptrdiff_t)(sep - locale), locale, &sep[3]); + asprintf(&lang_locale, "%.*s%s", + (int)(sep - locale), + locale, &sep[3]); } } break; @@ -1021,16 +1081,8 @@ main(int argc, char **argv) whatis_proto = new_sbuf(); whatis_final = new_sbuf(); - if ((machine = getenv("MACHINE")) == NULL) { - static struct utsname utsname; - - if (uname(&utsname) == -1) - err(1, "uname"); - machine = utsname.machine; - } - - if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) - machine_arch = MACHINE_ARCH; + if ((machine = getenv("MACHINE")) == NULL) + machine = MACHINE; if (common_output != NULL && (fp = open_output(common_output)) == NULL) err(1, "%s", common_output);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201402270043.s1R0hAU9098502>