summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2008-02-13 10:20:37 -0800
committerAaron Plattner <aplattner@nvidia.com>2008-02-13 10:20:37 -0800
commitece22163b2913af4823bc4aad397a7e32dc5d4e0 (patch)
tree6fed87d929401b49319a7f23ab61ce2180e71196
parentb581a5923ce164af5c8cd5634f4cba4fd098f711 (diff)
1.0-71671.0-7167
-rw-r--r--files.c16
-rw-r--r--format.c61
-rw-r--r--format.h2
-rw-r--r--kernel.c69
-rw-r--r--log.c9
-rw-r--r--misc.c82
-rw-r--r--misc.h35
-rw-r--r--user-interface.c65
8 files changed, 159 insertions, 180 deletions
diff --git a/files.c b/files.c
index a407520..ea6c028 100644
--- a/files.c
+++ b/files.c
@@ -394,7 +394,13 @@ void select_tls_class(Options *op, Package *p)
for (i = 0; i < p->num_entries; i++) {
if ((p->entries[i].flags & FILE_CLASS_NEW_TLS) &&
(p->entries[i].flags & FILE_CLASS_NATIVE)) {
- nvfree(p->entries[i].dst);
+ /*
+ * XXX don't try to free the destination string for
+ * these invalidated TLS libraries; this prevents
+ * a crash on some Slackware 10.0 installations that
+ * I've been unable to reproduce/root cause.
+ */
+ /* nvfree(p->entries[i].dst); */
p->entries[i].flags &= ~FILE_TYPE_MASK;
p->entries[i].dst = NULL;
}
@@ -433,7 +439,13 @@ void select_tls_class(Options *op, Package *p)
for (i = 0; i < p->num_entries; i++) {
if ((p->entries[i].flags & FILE_CLASS_NEW_TLS) &&
(p->entries[i].flags & FILE_CLASS_COMPAT32)) {
- nvfree(p->entries[i].dst);
+ /*
+ * XXX don't try to free the destination string for
+ * these invalidated TLS libraries; this prevents
+ * a crash on some Slackware 10.0 installations that
+ * I've been unable to reproduce/root cause.
+ */
+ /* nvfree(p->entries[i].dst); */
p->entries[i].flags &= ~FILE_TYPE_MASK;
p->entries[i].dst = NULL;
}
diff --git a/format.c b/format.c
index 758d9cf..72f05aa 100644
--- a/format.c
+++ b/format.c
@@ -41,6 +41,24 @@ static unsigned short __terminal_width = 0;
#define DEFAULT_WIDTH 75
+/*
+ * Format and display a printf style string such that it fits within
+ * the terminal width
+ */
+
+#define NV_VFORMAT(stream, wb, prefix, fmt) \
+do { \
+ char *buf; \
+ NV_VSNPRINTF(buf, fmt); \
+ vformat(stream, wb, prefix, buf); \
+ free (buf); \
+} while(0)
+
+
+static void vformat(FILE *stream, const int wb,
+ const char *prefix, const char *buf);
+
+
/*
* reset_current_terminal_width() - if new_val is zero, then use the
* TIOCGWINSZ ioctl to get the current width of the terminal, and
@@ -73,11 +91,7 @@ void reset_current_terminal_width(unsigned short new_val)
void fmtout(const char *fmt, ...)
{
- va_list ap;
-
- va_start(ap, fmt);
- vformat(stdout, TRUE, NULL, fmt, ap);
- va_end(ap);
+ NV_VFORMAT(stdout, TRUE, NULL, fmt);
} /* fmtout() */
@@ -90,11 +104,7 @@ void fmtout(const char *fmt, ...)
void fmtoutp(const char *prefix, const char *fmt, ...)
{
- va_list ap;
-
- va_start(ap, fmt);
- vformat(stdout, TRUE, prefix, fmt, ap);
- va_end(ap);
+ NV_VFORMAT(stdout, TRUE, prefix, fmt);
} /* fmtoutp() */
@@ -107,11 +117,7 @@ void fmtoutp(const char *prefix, const char *fmt, ...)
void fmterr(const char *fmt, ...)
{
- va_list ap;
-
- va_start(ap, fmt);
- vformat(stderr, TRUE, NULL, fmt, ap);
- va_end(ap);
+ NV_VFORMAT(stderr, TRUE, NULL, fmt);
} /* fmterr() */
@@ -124,11 +130,7 @@ void fmterr(const char *fmt, ...)
void fmterrp(const char *prefix, const char *fmt, ...)
{
- va_list ap;
-
- va_start(ap, fmt);
- vformat(stderr, TRUE, prefix, fmt, ap);
- va_end(ap);
+ NV_VFORMAT(stderr, TRUE, prefix, fmt);
} /* fmterrp() */
@@ -136,7 +138,7 @@ void fmterrp(const char *prefix, const char *fmt, ...)
/*
* format() & vformat() - these takes a printf-style format string and
- * a variable list of args. We use assemble_string to generate the
+ * a variable list of args. We use NV_VSNPRINTF to generate the
* desired string, and then call nv_format_text_rows() to format the
* string so that not more than __terminal_width characters are
* printed across.
@@ -151,29 +153,24 @@ void fmterrp(const char *prefix, const char *fmt, ...)
void format(FILE *stream, const char *prefix, const char *fmt, ...)
{
- va_list ap;
-
- va_start(ap, fmt);
- vformat(stream, TRUE, prefix, fmt, ap);
- va_end(ap);
+ NV_VFORMAT(stream, TRUE, prefix, fmt);
} /* format() */
-void vformat(FILE *stream, const int wb,
- const char *prefix, const char *fmt, va_list ap)
+
+
+static void vformat(FILE *stream, const int wb,
+ const char *prefix, const char *buf)
{
- char *buf;
int i;
TextRows *t;
if (!__terminal_width) reset_current_terminal_width(0);
- buf = assemble_string(fmt, ap);
t = nv_format_text_rows(prefix, buf, __terminal_width, wb);
for (i = 0; i < t->n; i++) fprintf(stream, "%s\n", t->t[i]);
nv_free_text_rows(t);
- free(buf);
-} /* vformat_b() */
+} /* vformat() */
diff --git a/format.h b/format.h
index a629470..b82660b 100644
--- a/format.h
+++ b/format.h
@@ -37,7 +37,5 @@ void fmtoutp(const char *prefix, const char *fmt, ...);
void fmterr(const char *fmt, ...);
void fmterrp(const char *prefix, const char *fmt, ...);
void format(FILE *stream, const char *prefix, const char *fmt, ...);
-void vformat(FILE *stream, const int wb,
- const char *prefix, const char *fmt, va_list ap);
#endif /* __NVIDIA_INSTALLER_FORMAT_H__ */
diff --git a/kernel.c b/kernel.c
index 227f665..6f13b56 100644
--- a/kernel.c
+++ b/kernel.c
@@ -28,6 +28,7 @@
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <ctype.h>
#include <stdlib.h>
#include <dirent.h>
@@ -52,7 +53,7 @@ static int rmmod_kernel_module(Options *op, const char *);
static PrecompiledInfo *download_updated_kernel_interface(Options*, Package*,
const char*);
static int rivafb_check(Options *op, Package *p);
-static void rivafb_module_check(Options *op, Package *p);
+static void change_page_attr_check(Options *op, Package *p);
static PrecompiledInfo *scan_dir(Options *op, Package *p,
const char *directory_name,
@@ -450,7 +451,7 @@ int build_kernel_module(Options *op, Package *p)
}
if (!rivafb_check(op, p)) return FALSE;
- rivafb_module_check(op, p);
+ change_page_attr_check(op, p);
cmd = nvstrcat("cd ", p->kernel_module_build_directory,
"; make print-module-filename",
@@ -627,15 +628,14 @@ int build_kernel_interface(Options *op, Package *p)
/*
* test_kernel_module() - attempt to insmod the kernel module and then
* rmmod it. Return TRUE if the insmod succeeded, or FALSE otherwise.
- *
- * Pass the special silence_nvidia_output option to the kernel module
- * to prevent any console output while testing.
*/
int test_kernel_module(Options *op, Package *p)
{
char *cmd = NULL, *data;
- int ret;
+ int old_loglevel, new_loglevel = 0;
+ int ret, name[] = { CTL_KERN, KERN_PRINTK };
+ size_t len = sizeof(int);
/*
* If we're building/installing for a different kernel, then we
@@ -644,10 +644,20 @@ int test_kernel_module(Options *op, Package *p)
if (op->kernel_name) return TRUE;
+ /*
+ * Temporarily disable most console messages to keep the curses
+ * interface from being clobbered when the module is loaded.
+ * Save the original console loglevel to allow restoring it once
+ * we're done.
+ */
+ if (!sysctl(name, 2, &old_loglevel, &len, NULL, 0)) {
+ new_loglevel = 2; /* KERN_CRIT */
+ sysctl(name, 2, NULL, 0, &new_loglevel, len);
+ }
+
cmd = nvstrcat(op->utils[INSMOD], " ",
p->kernel_module_build_directory, "/",
- p->kernel_module_filename, " silence_nvidia_output=1",
- NULL);
+ p->kernel_module_filename, NULL);
/* only output the result of the test if in expert mode */
@@ -677,7 +687,7 @@ int test_kernel_module(Options *op, Package *p)
*/
cmd = nvstrcat(op->utils[DMESG], " | ",
- op->utils[TAIL], " -n 5", NULL);
+ op->utils[TAIL], " -n 15", NULL);
if (!run_command(op, cmd, &data, FALSE, 0, TRUE))
ui_log(op, "Kernel messages:\n%s", data);
@@ -697,6 +707,8 @@ int test_kernel_module(Options *op, Package *p)
if (cmd) free(cmd);
if (data) free(data);
+ if (new_loglevel != 0) sysctl(name, 2, NULL, 0, &old_loglevel, len);
+
return ret;
} /* test_kernel_module() */
@@ -1408,6 +1420,16 @@ int check_cc_version(Options *op, Package *p)
return TRUE;
}
+ /*
+ * Check if the libc development headers are installed; we need
+ * these to build the gcc version check utility.
+ */
+ if (access("/usr/include/stdio.h", F_OK) == -1) {
+ ui_error(op, "You do not appear to have libc header files "
+ "installed on your system. Please install your "
+ "distribution's libc development package.");
+ return FALSE;
+ }
CC = getenv("CC");
if (!CC) CC = "cc";
@@ -1478,37 +1500,34 @@ static int rivafb_check(Options *op, Package *p)
} /* rivafb_check() */
-
/*
- * rivafb_module_check() - run the rivafb_module_sanity_check
- * conftest; if the test prints anything, print the warning text
- * outputted by the test.
+ * change_page_attr_check() - run the change_page_attr_sanity_check
+ * conftest; if the test fails, print a warning messages, but continue
+ * the installation.
*/
-static void rivafb_module_check(Options *op, Package *p)
+static void change_page_attr_check(Options *op, Package *p)
{
+#if defined(NV_X86_64)
char *cmd, *result;
int ret;
-
- ui_log(op, "Performing rivafb module check.");
-
+
+ ui_log(op, "Performing change_page_attr() check.");
+
cmd = nvstrcat("sh ", p->kernel_module_build_directory,
"/conftest.sh cc ",
op->kernel_source_path, " ",
op->kernel_output_path, " ",
- "rivafb_module_sanity_check just_msg", NULL);
+ "change_page_attr_sanity_check just_msg", NULL);
ret = run_command(op, cmd, &result, FALSE, 0, TRUE);
-
nvfree(cmd);
-
- if (result && result[0]) {
- ui_warn(op, result);
- }
-
+
+ if (result && *result) ui_warn(op, result);
nvfree(result);
-} /* rivafb_module_check() */
+#endif /* NV_X86_64 */
+}
diff --git a/log.c b/log.c
index 96a29e9..cc1d48e 100644
--- a/log.c
+++ b/log.c
@@ -186,13 +186,10 @@ void log_printf(Options *op, const int wb,
char *buf;
int i;
TextRows *t;
- va_list ap;
-
+
if (!op->logging) return;
- va_start(ap, fmt);
-
- buf = assemble_string(fmt, ap);
+ NV_VSNPRINTF(buf, fmt);
t = nv_format_text_rows(prefix, buf, LOG_WIDTH, wb);
for (i = 0; i < t->n; i++) fprintf(log_file_stream, "%s\n", t->t[i]);
@@ -200,8 +197,6 @@ void log_printf(Options *op, const int wb,
nv_free_text_rows(t);
nvfree(buf);
- va_end(ap);
-
/* flush, just to be safe */
fflush(log_file_stream);
diff --git a/misc.c b/misc.c
index 5fddf54..6c1c505 100644
--- a/misc.c
+++ b/misc.c
@@ -232,62 +232,6 @@ char *read_next_word (char *buf, char **e)
/*
- * assemble_string() - takes a fmt string and a va_list, and uses
- * vsnprintf to build the resulting string. The caller of this
- * function is responsible for freeing the returned string.
- *
- * XXX replace this with a macro (see X driver sources)
- */
-
-char *assemble_string(const char *fmt, va_list ap)
-{
- char *buf;
- int current_len, len, done;
-
- if (!fmt) return NULL;
-
- done = FALSE;
- current_len = NV_LINE_LEN;
-
- do {
- buf = (char *) nvalloc (current_len);
-
- len = vsnprintf (buf, current_len, fmt, ap);
-
- if ((len == -1) || len > current_len) {
-
- /*
- * if we get in here we know that vsnprintf had to
- * truncate the string to make it fit in the buffer... we
- * need to extend the buffer to encompass the string.
- * Unfortunately, we have to deal with two different
- * semantics of the return value from (v)snprintf:
- *
- * -1 when the buffer is not long enough (glibc < 2.1)
- *
- * or
- *
- * the length the string would have been if the buffer had
- * been large enough (glibc >= 2.1)
- */
-
- if (len == -1) current_len += NV_LINE_LEN;
- else current_len = len+1;
-
- free (buf);
- }
- else done = TRUE;
-
- } while (!done);
-
- return buf;
-
-} /* assemble_string() */
-
-
-
-
-/*
* check_euid() - this function checks that the effective uid of this
* application is root, and calls the ui to print an error if it's not
* root.
@@ -876,11 +820,8 @@ int continue_after_error(Options *op, const char *fmt, ...)
{
char *msg;
int ret;
- va_list ap;
- va_start (ap, fmt);
- msg = assemble_string (fmt, ap);
- va_end (ap);
+ NV_VSNPRINTF(msg, fmt);
ret = ui_yes_no(op, TRUE, "The installer has encountered the following "
"error during installation: '%s'. Continue anyway? "
@@ -1395,6 +1336,26 @@ int check_runtime_configuration(Options *op, Package *p)
/*
+ * collapse_multiple_slashes() - remove any/all occurances of "//" from the
+ * argument string.
+ */
+
+void collapse_multiple_slashes(char *s)
+{
+ char *p;
+ unsigned int i, len;
+
+ while ((p = strstr(s, "//")) != NULL) {
+ p++; /* advance to second '/' */
+ while (*p == '/') {
+ len = strlen(p);
+ for (i = 0; i < len; i++) p[i] = p[i+1];
+ }
+ }
+}
+
+
+/*
* rtld_test_internal() - this routine writes the test binaries to a file
* and performs the test; the caller (rtld_test()) selects which array data
* is used (native, compat_32).
@@ -1474,6 +1435,7 @@ static int rtld_test_internal(Options *op, Package *p,
name = nvstrdup(p->entries[i].dst);
if (!name) goto next;
+ collapse_multiple_slashes(data);
s = strstr(name, ".so.1");
if (!s) goto next;
*(s + strlen(".so.1")) = '\0';
diff --git a/misc.h b/misc.h
index 74b3e4b..532fc5a 100644
--- a/misc.h
+++ b/misc.h
@@ -30,10 +30,45 @@
#include <stdio.h>
#include <stdarg.h>
+#include <stdlib.h>
#include "nvidia-installer.h"
#include "command-list.h"
+/*
+ * NV_VSNPRINTF() - takes a fmt string, and uses vsnprintf to build
+ * the resulting string whic it assigns to buf. The caller of this
+ * function is responsible for freeing the returned string.
+ */
+#define NV_VSNPRINTF(buf, fmt) \
+do { \
+ if (!fmt) { \
+ (buf) = NULL; \
+ } else { \
+ va_list ap; \
+ int len, current_len = NV_LINE_LEN; \
+ \
+ (buf) = malloc(current_len); \
+ \
+ while (1) { \
+ va_start(ap, fmt); \
+ len = vsnprintf((buf), current_len, (fmt), ap); \
+ va_end(ap); \
+ \
+ if ((len > -1) && (len < current_len)) { \
+ break; \
+ } else if (len > -1) { \
+ current_len = len + 1; \
+ } else { \
+ current_len += NV_LINE_LEN; \
+ } \
+ \
+ (buf) = realloc(buf, current_len); \
+ } \
+ } \
+} while (0)
+
+
void *nvalloc(size_t size);
void *nvrealloc(void *ptr, size_t size);
char *nvstrdup(const char *s);
diff --git a/user-interface.c b/user-interface.c
index 4bfed83..1ec24ea 100644
--- a/user-interface.c
+++ b/user-interface.c
@@ -175,13 +175,10 @@ int ui_init(Options *op)
void ui_set_title(Options *op, const char *fmt, ...)
{
char *title;
- va_list ap;
if (op->silent) return;
- va_start(ap, fmt);
- title = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(title, fmt);
__ui->set_title(op, title);
free(title);
@@ -197,11 +194,8 @@ void ui_set_title(Options *op, const char *fmt, ...)
char *ui_get_input(Options *op, const char *def, const char *fmt, ...)
{
char *msg, *tmp = NULL, *ret;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
if (op->no_questions) {
ret = nvstrdup(def ? def : "");
@@ -244,11 +238,8 @@ int ui_display_license (Options *op, const char *license)
void ui_error(Options *op, const char *fmt, ...)
{
char *msg;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
__ui->message(op, NV_MSG_LEVEL_ERROR, msg);
log_printf(op, TRUE, "ERROR: ", msg);
@@ -262,11 +253,8 @@ void ui_error(Options *op, const char *fmt, ...)
void ui_warn(Options *op, const char *fmt, ...)
{
char *msg;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
__ui->message(op, NV_MSG_LEVEL_WARNING, msg);
log_printf(op, TRUE, "WARNING: ", msg);
@@ -280,11 +268,8 @@ void ui_warn(Options *op, const char *fmt, ...)
void ui_message(Options *op, const char *fmt, ...)
{
char *msg;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
if (!op->silent) __ui->message(op, NV_MSG_LEVEL_MESSAGE, msg);
@@ -298,11 +283,8 @@ void ui_message(Options *op, const char *fmt, ...)
void ui_log(Options *op, const char *fmt, ...)
{
char *msg;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
if (!op->silent) __ui->message(op, NV_MSG_LEVEL_LOG, msg);
log_printf(op, TRUE, NV_BULLET_STR, msg);
@@ -320,13 +302,10 @@ void ui_log(Options *op, const char *fmt, ...)
void ui_expert(Options *op, const char *fmt, ...)
{
char *msg;
- va_list ap;
if (!op->expert) return;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
if (!op->silent) __ui->message(op, NV_MSG_LEVEL_LOG, msg);
log_printf(op, FALSE, NV_BULLET_STR, msg);
@@ -340,11 +319,8 @@ void ui_expert(Options *op, const char *fmt, ...)
void ui_command_output(Options *op, const char *fmt, ...)
{
char *msg;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
if (!op->silent) __ui->command_output(op, msg);
@@ -364,13 +340,10 @@ int ui_approve_command_list(Options *op, CommandList *c, const char *fmt, ...)
{
char *msg;
int ret;
- va_list ap;
if (!op->expert || op->no_questions) return TRUE;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
ret = __ui->approve_command_list(op, c, msg);
free(msg);
@@ -391,11 +364,8 @@ int ui_yes_no (Options *op, const int def, const char *fmt, ...)
{
char *msg, *tmp = NULL;
int ret;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
if (op->no_questions) {
ret = def;
@@ -421,15 +391,12 @@ int ui_yes_no (Options *op, const int def, const char *fmt, ...)
void ui_status_begin(Options *op, const char *title, const char *fmt, ...)
{
char *msg;
- va_list ap;
log_printf(op, TRUE, NV_BULLET_STR, title);
if (op->silent) return;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
__ui->status_begin(op, title, msg);
free(msg);
@@ -440,13 +407,10 @@ void ui_status_begin(Options *op, const char *title, const char *fmt, ...)
void ui_status_update(Options *op, const float percent, const char *fmt, ...)
{
char *msg;
- va_list ap;
if (op->silent) return;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
__ui->status_update(op, percent, msg);
free(msg);
@@ -457,11 +421,8 @@ void ui_status_update(Options *op, const float percent, const char *fmt, ...)
void ui_status_end(Options *op, const char *fmt, ...)
{
char *msg;
- va_list ap;
- va_start(ap, fmt);
- msg = assemble_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
if (!op->silent) __ui->status_end(op, msg);
log_printf(op, TRUE, NV_BULLET_STR, msg);