view toys/other/modinfo.c @ 1278:324306321d82 draft

Initial cleanup of last: mostly whitespace, move no record test to start of loop, don't bother to stat an empty file to report when an empty log was created (just report current time).
author Rob Landley <rob@landley.net>
date Sat, 10 May 2014 13:20:03 -0500
parents 436c60124674
children fc1bb49e58a9
line wrap: on
line source

/* modinfo.c - Display module info
 *
 * Copyright 2012 Andre Renaud <andre@bluewatersys.com>

USE_MODINFO(NEWTOY(modinfo, "<1b:k:F:0", TOYFLAG_BIN))

config MODINFO
  bool "modinfo"
  default y
  help
    usage: modinfo [-0] [-b basedir] [-k kernrelease] [-F field] [modulename...]
    Display module fields for all specified modules, looking in
    <basedir>/lib/modules/<kernrelease>/ (kernrelease defaults to uname -r).
*/

#define FOR_modinfo
#include "toys.h"

GLOBALS(
  char *field;
  char *knam;
  char *base;

  long mod;
)

static void output_field(char *field, char *value)
{
  if (!TT.field) xprintf("%s:%*c", field, 15 - strlen(field), ' ');
  else if (strcmp(TT.field, field)) return;
  xprintf("%s", value);
  xputc((toys.optflags & FLAG_0) ? 0 : '\n');
}

static void modinfo_file(char *full_name)
{
  int fd, len, i;
  char *buf = 0, *pos, *modinfo_tags[] = {
    "alias", "license", "description", "author", "firmware",
    "vermagic", "srcversion", "intree", "depends", "parm",
    "parmtype",
  };

  if (-1 != (fd = open(full_name, O_RDONLY))) {
    len = fdlength(fd);
    if (!(buf = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0))) close(fd);
  }

  if (!buf) {
    perror_msg("%s", full_name);
    return;
  } 

  output_field("filename", full_name);

  for (pos = buf; pos < buf+len; pos++) {
    if (*pos) continue;

    for (i = 0; i < sizeof(modinfo_tags) / sizeof(*modinfo_tags); i++) {
      char *str = modinfo_tags[i];
      int len = strlen(str);

      if (!strncmp(pos+1, str, len) && pos[len+1] == '=') 
        output_field(str, pos+len+2);
    }
  }

  munmap(buf, len);
  close(fd);
}

static int check_module(struct dirtree *new)
{
  if (S_ISREG(new->st.st_mode)) {
    char *s;

    for (s = toys.optargs[TT.mod]; *s; s++) {
      int len = 0;

      // The kernel treats - and _ the same, so we should too.
      for (len = 0; s[len]; len++) {
        if (s[len] == '-' && new->name[len] == '_') continue;
        if (s[len] == '_' && new->name[len] == '-') continue;
        if (s[len] != new->name[len]) break;
      }
      if (s[len] || strcmp(new->name+len, ".ko")) break;

      modinfo_file(s = dirtree_path(new, NULL));
      free(s);

      return DIRTREE_ABORT;
    }
  }

  return dirtree_notdotdot(new);
}

void modinfo_main(void)
{
  for(TT.mod = 0; TT.mod<toys.optc; TT.mod++) {
    char *s = strstr(toys.optargs[TT.mod], ".ko");

    if (s && !s[3]) modinfo_file(toys.optargs[TT.mod]);
    else {
      struct utsname uts;

      if (uname(&uts) < 0) perror_exit("bad uname");
      if (snprintf(toybuf, sizeof(toybuf), "%s/lib/modules/%s",
          (toys.optflags & FLAG_b) ? TT.base : "",
          (toys.optflags & FLAG_k) ? TT.knam : uts.release) >= sizeof(toybuf))
            perror_exit("basedir/kernrelease too long");
      dirtree_read(toybuf, check_module);
    }
  }
}