summaryrefslogtreecommitdiff
path: root/os_cmd/Linux/ossvermagic/ossvermagic.c
diff options
context:
space:
mode:
Diffstat (limited to 'os_cmd/Linux/ossvermagic/ossvermagic.c')
-rw-r--r--os_cmd/Linux/ossvermagic/ossvermagic.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/os_cmd/Linux/ossvermagic/ossvermagic.c b/os_cmd/Linux/ossvermagic/ossvermagic.c
new file mode 100644
index 0000000..7af4666
--- /dev/null
+++ b/os_cmd/Linux/ossvermagic/ossvermagic.c
@@ -0,0 +1,325 @@
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <elf.h>
+#define CONFIGURE_C
+#include "oss_config.h"
+
+int elf_verbose = 0;
+
+#ifdef __x86_64__
+#define ELF64
+#define ELF_LOAD_SYMTAB elf_load_symtab
+#else
+#define ELF32
+#define ELF_LOAD_SYMTAB elf_load_symtab
+#endif
+#include "../../../setup/elflib.inc"
+
+char *fname;
+int ok;
+int quiet = 0;
+int verbose = 0;
+int once = 0;
+int exit_status = -1;
+int check_compile_vermagic = 0;
+
+static void
+sym_callback (char *buffer, int blen, Elf_Sym * sym, char *name, int addr)
+{
+
+ char tmp[256], *vermagic = tmp;
+
+ ok = 1;
+ exit_status = 0;
+
+ if (verbose)
+ printf ("Vermagic buffer at %x\n", addr);
+
+ elf_read_datasym (buffer, blen, sym, addr, tmp, sizeof (tmp));
+
+ if (strncmp (vermagic, "vermagic=", 9) == 0)
+ vermagic += 9;
+
+ if (quiet)
+ printf ("%s\n", vermagic);
+ else
+ printf ("%s: '%s'\n", fname, vermagic);
+
+ if (once)
+ exit (0);
+}
+
+static void
+find_vermagic (char *fname)
+{
+ ok = 0;
+
+ if (verbose)
+ printf ("ELF scan %s\n", fname);
+
+ ok = ELF_LOAD_SYMTAB (fname, "vermagic", sym_callback);
+ if (!ok)
+ ok = ELF_LOAD_SYMTAB (fname, "__mod_vermagic", sym_callback);
+ if (!ok)
+ ELF_LOAD_SYMTAB (fname, "__oss_compile_vermagic", sym_callback);
+}
+
+static void
+find_link_vermagic (char *fname)
+{
+ if (verbose)
+ printf ("ELF scan %s\n", fname);
+
+ ELF_LOAD_SYMTAB (fname, "__oss_compile_vermagic", sym_callback);
+}
+
+static void
+check_gzipped_module (char *fname)
+{
+ char tmp[1024];
+
+ sprintf (tmp, "gunzip -c %s > /tmp/oss.tmpmodule", fname);
+ unlink ("/tmp/oss.tmpmodule");
+
+ if (system (tmp) != 0)
+ {
+ unlink ("/tmp/oss.tmpmodule");
+ return;
+ }
+
+ find_vermagic ("/tmp/oss.tmpmodule");
+ unlink ("/tmp/oss.tmpmodule");
+}
+
+static void
+check_bzipped_module (char *fname)
+{
+ char tmp[1024];
+
+ sprintf (tmp, "bunzip2 -c %s > /tmp/oss.tmpmodule", fname);
+ unlink ("/tmp/oss.tmpmodule");
+
+ if (system (tmp) != 0)
+ {
+ unlink ("/tmp/oss.tmpmodule");
+ return;
+ }
+
+ find_vermagic ("/tmp/oss.tmpmodule");
+ unlink ("/tmp/oss.tmpmodule");
+}
+
+static void
+scan_dir (char *dirname)
+{
+ char tmp[1024];
+ DIR *dir;
+ struct dirent *de;
+
+ if ((dir = opendir (dirname)) == NULL)
+ return;
+
+ while ((de = readdir (dir)))
+ {
+ struct stat st;
+
+ if (de->d_name[0] == '.')
+ continue;
+
+ sprintf (tmp, "%s/%s", dirname, de->d_name);
+
+ if (stat (tmp, &st) == -1)
+ {
+ perror (tmp);
+ return;
+ }
+
+ if (S_ISDIR (st.st_mode))
+ scan_dir (tmp);
+ else
+ {
+ char *p;
+
+ if (verbose)
+ printf ("Checking %s\n", tmp);
+ p = tmp + strlen (tmp) - 3; // Seek the .gz suffix
+ if (strcmp (p, ".gz") == 0)
+ {
+ fname = tmp;
+ check_gzipped_module (tmp);
+ continue;
+ }
+
+ p = tmp + strlen (tmp) - 4; // Seek the .bz2 suffix
+ if (strcmp (p, ".bz2") == 0)
+ {
+ fname = tmp;
+ check_bzipped_module (tmp);
+ continue;
+ }
+
+ fname = tmp;
+ find_vermagic (tmp);
+ }
+ }
+
+ closedir (dir);
+}
+
+static void
+find_system_vermagic (void)
+{
+ struct utsname un;
+ char dirname[1024];
+
+ struct stat st;
+
+ if (uname (&un) == -1)
+ {
+ perror ("uname");
+ exit (-1);
+ }
+
+ sprintf (dirname, "/lib/modules/%s/kernel", un.release);
+
+ if (stat (dirname, &st) == -1)
+ {
+ perror (dirname);
+ fprintf (stderr, "Kernel modules not available\n");
+ exit (-1);
+ }
+
+ quiet = 1;
+ once = 1;
+ scan_dir (dirname);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i, ok;
+ int do_sys = 0;
+ int valid = 0;
+
+ if (argc < 2)
+ exit (-1);
+
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp (argv[i], "-r") == 0)
+ {
+ /*
+ * Check if the system is 2.6.20 or later which is
+ * always compiled with CONFIG_REGPARM.
+ */
+
+ struct utsname un;
+ int a, b, c;
+
+ if (uname (&un) == -1)
+ {
+ perror ("uname");
+ exit (-1);
+ }
+
+ if (sscanf (un.release, "%d.%d.%d", &a, &b, &c) != 3)
+ {
+ fprintf (stderr, "Unrecognized kernel release '%s'\n",
+ un.release);
+ exit (0); /* Assume it's some future kernel */
+ }
+
+ if (a > 2)
+ exit (0); /* Always REGPARM */
+ if (b > 6)
+ exit (0); /* Always REGPARM */
+ if (c >= 20)
+ exit (0); /* Always REGPARM */
+
+ exit (1); /* Don't know */
+ }
+
+ if (strcmp (argv[i], "-s") == 0)
+ do_sys = 1;
+ if (strcmp (argv[i], "-v") == 0)
+ verbose++;
+ if (strcmp (argv[i], "-z") == 0)
+ valid = 1;
+ if (strcmp (argv[i], "-u") == 0)
+ check_compile_vermagic = 1;
+ }
+
+ if (!valid)
+ {
+ fprintf (stderr,
+ "%s: This program is reserved for use by Open Sound System\n",
+ argv[0]);
+ exit (-1);
+ }
+
+ elf_verbose = verbose;
+
+ if (do_sys)
+ {
+ ok = 0;
+ if (fork () == 0)
+ find_system_vermagic ();
+ else
+ {
+ int status;
+ wait (&status);
+ unlink ("/tmp/oss.tmpmodule");
+ exit (WEXITSTATUS (status));
+ }
+
+ if (!ok)
+ exit (-1);
+ exit (0);
+ }
+
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp (argv[i], "-q") == 0)
+ {
+ quiet = 1;
+ continue;
+ }
+
+ if (strcmp (argv[i], "-1") == 0)
+ {
+ once = 1;
+ continue;
+ }
+
+ fname = argv[i];
+ ok = 0;
+
+ if (*fname != '-')
+ {
+ if (check_compile_vermagic == 0) find_vermagic (fname);
+ else find_link_vermagic (fname);
+ }
+ }
+
+ exit (exit_status);
+}