summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2014-02-09 11:41:07 -0800
committerAaron Plattner <aplattner@nvidia.com>2014-02-09 11:41:07 -0800
commit63b65ddce0396ef7b9b2f8e5bfd877c2a227155c (patch)
treeaeac5f83aed556d8ac64665c88f06c6f2381cb63
parente49143d67bf5c67efb9293455d5d69d068c23e6c (diff)
334.16334.16
-rw-r--r--Makefile5
-rw-r--r--backup.c67
-rw-r--r--command-list.c43
-rw-r--r--common-utils/common-utils.c307
-rw-r--r--common-utils/common-utils.h89
-rw-r--r--common-utils/gen-manpage-opts-helper.c33
-rw-r--r--common-utils/msg.c416
-rw-r--r--common-utils/msg.h137
-rw-r--r--common-utils/src.mk2
-rw-r--r--files.c69
-rw-r--r--install-from-cwd.c170
-rw-r--r--kernel.c147
-rw-r--r--makeself-help-script.c9
-rw-r--r--manifest.c3
-rw-r--r--misc.c330
-rw-r--r--misc.h19
-rw-r--r--ncurses-ui.c170
-rw-r--r--nvidia-installer-ui.h13
-rw-r--r--nvidia-installer.c45
-rw-r--r--nvidia-installer.h43
-rw-r--r--stream-ui.c152
-rw-r--r--user-interface.c30
-rw-r--r--user-interface.h5
-rw-r--r--utils.mk1
-rw-r--r--version.mk2
25 files changed, 1331 insertions, 976 deletions
diff --git a/Makefile b/Makefile
index dd2da20..e34851b 100644
--- a/Makefile
+++ b/Makefile
@@ -96,7 +96,7 @@ GEN_UI_ARRAY = $(OUTPUTDIR)/gen-ui-array
CONFIG_H = $(OUTPUTDIR)/config.h
MANPAGE = $(OUTPUTDIR)/nvidia-installer.1.gz
-GEN_MANPAGE_OPTS = $(OUTPUTDIR)/gen-manpage-opts
+GEN_MANPAGE_OPTS = $(OUTPUTDIR_ABSOLUTE)/gen-manpage-opts
OPTIONS_1_INC = $(OUTPUTDIR)/options.1.inc
# Setup some architecture specific build options
@@ -158,6 +158,7 @@ MKPRECOMPILED_OBJS = $(call BUILD_OBJECT_LIST,$(MKPRECOMPILED_SRC))
MAKESELF_HELP_SCRIPT_SRC = makeself-help-script.c
MAKESELF_HELP_SCRIPT_SRC += $(COMMON_UTILS_DIR)/common-utils.c
MAKESELF_HELP_SCRIPT_SRC += $(COMMON_UTILS_DIR)/nvgetopt.c
+MAKESELF_HELP_SCRIPT_SRC += $(COMMON_UTILS_DIR)/msg.c
BUILD_MAKESELF_OBJECT_LIST = \
$(patsubst %.o,%.makeself.o,$(call BUILD_OBJECT_LIST,$(1)))
@@ -371,7 +372,7 @@ $(GEN_MANPAGE_OPTS): $(GEN_MANPAGE_OPTS_OBJS)
$(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_BIN_LDFLAGS) $^ -o $@
$(OPTIONS_1_INC): $(GEN_MANPAGE_OPTS)
- @./$< > $@
+ @$< > $@
$(MANPAGE): nvidia-installer.1.m4 $(OPTIONS_1_INC) $(VERSION_MK)
$(call quiet_cmd,M4) \
diff --git a/backup.c b/backup.c
index e199396..02fce40 100644
--- a/backup.c
+++ b/backup.c
@@ -541,7 +541,7 @@ int log_mkdir(Options *op, const char *dirs)
*/
static int reverse_strlen_compare(const void *a, const void *b)
{
- return strlen((const char *)b) - strlen((const char *)a);
+ return strlen(*(char * const *)b) - strlen(*(char * const *)a);
}
@@ -586,7 +586,7 @@ static int rmdir_recursive(Options *op)
qsort(dirs, lines, sizeof(char*), reverse_strlen_compare);
- for (i = lines; i < lines; i++) {
+ for (i = 0; i < lines; i++) {
if (dirs[i]) {
/* Ignore empty lines and the backup directory itself, since it is
* never empty as long as the dirs file is still around. */
@@ -1094,46 +1094,13 @@ static int check_backup_log_entries(Options *op, BackupInfo *b)
switch (e->num) {
case INSTALLED_FILE:
-
- /* check if the file is still there */
-
- if (access(e->filename, F_OK) == -1) {
- ui_log(op, "Unable to access previously installed file "
- "'%s' (%s).", e->filename, strerror(errno));
- ret = e->ok = FALSE;
- } else {
- /* check if the file still has the same crc; if not, try
- * un-prelinking it and check the crc again */
- if (!verify_crc(op, e->filename, e->crc, &crc)) {
- ui_expert(op, "The previously installed file '%s' has a "
- "different checksum (%ul) than when it was "
- "installed (%ul). This may be due to prelinking; "
- "attempting `prelink -u %s` to restore the file.",
- e->filename, crc, e->crc, e->filename);
-
- if (unprelink(op, e->filename) != 0) {
- ui_log(op, "The previously installed file '%s' seems "
- "to have changed, but `prelink -u` failed; "
- "unable to restore '%s' to an un-prelinked "
- "state.", e->filename, e->filename);
- ret = e->ok = FALSE;
- } else if (!verify_crc(op, e->filename, e->crc, &crc)) {
- ui_log(op, "The previously installed file '%s' has a "
- "different checksum (%ul) after running `pre"
- "link -u` than when it was installed (%ul).",
- e->filename, crc, e->crc);
- ret = e->ok = FALSE;
- }
- if (ret) {
- ui_expert(op, "Un-prelinking successful: '%s' will "
- "be uninstalled.", e->filename);
- } else {
- ui_log(op, "Un-prelinking unsuccessful: '%s' will "
- "not be uninstalled.", e->filename);
- }
- }
- }
+ /* check if the file still matches its backup log entry */
+
+ e->ok = check_installed_file(op, e->filename, e->mode, e->crc,
+ ui_log);
+ ret = ret && e->ok;
+
ui_status_update(op, percent, "%s", e->filename);
break;
@@ -1317,6 +1284,11 @@ int check_for_existing_driver(Options *op, Package *p)
int ret = FALSE;
int localRet;
+ const char *choices[2] = {
+ "Continue installation",
+ "Abort installation"
+ };
+
if (!check_for_existing_rpms(op)) goto done;
localRet = get_installed_driver_version_and_descr(op, &version, &descr);
@@ -1359,13 +1331,12 @@ int check_for_existing_driver(Options *op, Package *p)
* downgrading is any different than upgrading.
*/
- if (!ui_yes_no(op, TRUE, "There appears to already be a driver installed "
- "on your system (version: %s). As part of "
- "installing this driver (version: %s), the existing "
- "driver will be uninstalled. Are you sure you want to "
- "continue? ('no' will abort installation)",
- version, p->version)) {
-
+ if (ui_multiple_choice(op, choices, 2, 0, "There appears to already be a "
+ "driver installed on your system (version: %s). As "
+ "part of installing this driver (version: %s), the "
+ "existing driver will be uninstalled. Are you sure "
+ "you want to continue?", version, p->version) == 1) {
+
ui_log(op, "Installation aborted.");
goto done;
}
diff --git a/command-list.c b/command-list.c
index a68a980..6b2c33c 100644
--- a/command-list.c
+++ b/command-list.c
@@ -335,15 +335,22 @@ CommandList *build_command_list(Options *op, Package *p)
*/
if (op->no_abi_note) {
- for (i = 0; i < p->num_entries; i++) {
- if (p->entries[i].type == FILE_TYPE_OPENGL_LIB) {
- tmp = nvstrcat(op->utils[OBJCOPY],
- " --remove-section=.note.ABI-tag ",
- p->entries[i].dst,
- " 2> /dev/null ; true", NULL);
- add_command(c, RUN_CMD, tmp);
- nvfree(tmp);
+
+ if (op->utils[OBJCOPY]) {
+ for (i = 0; i < p->num_entries; i++) {
+ if (p->entries[i].type == FILE_TYPE_OPENGL_LIB) {
+ tmp = nvstrcat(op->utils[OBJCOPY],
+ " --remove-section=.note.ABI-tag ",
+ p->entries[i].dst,
+ " 2> /dev/null ; true", NULL);
+ add_command(c, RUN_CMD, tmp);
+ nvfree(tmp);
+ }
}
+ } else {
+ ui_warn(op, "--no-abi-note option was specified but the system "
+ "utility `objcopy` (package 'binutils') was not found; this "
+ "operation will be skipped.");
}
}
@@ -358,13 +365,11 @@ CommandList *build_command_list(Options *op, Package *p)
* <Nigel.Spowage@energis.com>
*/
- if ( op->kernel_name && op->kernel_name[0] ) {
- tmp = nvstrcat(op->utils[DEPMOD], " -aq ", op->kernel_name, NULL);
- } else {
- tmp = nvstrcat(op->utils[DEPMOD], " -aq", NULL);
+ if (!op->no_kernel_module) {
+ tmp = nvstrcat(op->utils[DEPMOD], " -aq ", op->kernel_name, NULL);
+ add_command(c, RUN_CMD, tmp);
+ nvfree(tmp);
}
- add_command(c, RUN_CMD, tmp);
- nvfree(tmp);
/*
* if on SuSE or United Linux, also do `/usr/bin/chrc.config
@@ -624,16 +629,14 @@ static ConflictingFileInfo __xfree86_opengl_libs[] = {
{ "libglamoregl.", 13, /* strlen("libglamoregl.") */
NULL, CONFLICT_ARCH_ALL },
- /* Conflicting EGL libraries:
- * XXX we do not currently build 64-bit EGL libraries due to problems
- * with the ABI, so only conflict with 32-bit EGL libraries for now. */
+ /* Conflicting EGL libraries: */
{ "libEGL.", 7, /* strlen("libEGL.") */
- NULL, CONFLICT_ARCH_32 },
+ NULL, CONFLICT_ARCH_ALL },
{ "libGLESv1_CM.", 13, /* strlen("libGLESv1_CM." */
- NULL, CONFLICT_ARCH_32 },
+ NULL, CONFLICT_ARCH_ALL },
{ "libGLESv2.", 10, /* strlen("libGLESv2." */
- NULL, CONFLICT_ARCH_32 },
+ NULL, CONFLICT_ARCH_ALL },
{ NULL, 0, NULL, CONFLICT_ARCH_ALL }
};
diff --git a/common-utils/common-utils.c b/common-utils/common-utils.c
index 9bd349e..f581f0d 100644
--- a/common-utils/common-utils.c
+++ b/common-utils/common-utils.c
@@ -29,8 +29,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <sys/termios.h>
#include "common-utils.h"
@@ -354,311 +352,6 @@ char *nv_prepend_to_string_list(char *list, const char *item, const char *delim)
}
-/****************************************************************************/
-/* TextRows helper functions */
-/****************************************************************************/
-
-/*
- * nv_format_text_rows() - this function breaks the given string str
- * into some number of rows, where each row is not longer than the
- * specified width.
- *
- * If prefix is non-NULL, the first line is prepended with the prefix,
- * and subsequent lines are indented to line up with the prefix.
- *
- * If word_boundary is TRUE, then attempt to only break lines on
- * boundaries between words.
- */
-
-TextRows *nv_format_text_rows(const char *prefix,
- const char *str,
- int width, int word_boundary)
-{
- int len, prefix_len, z, w, i;
- char *line, *buf, *local_prefix, *a, *b, *c;
- TextRows *t;
-
- /* initialize the TextRows structure */
-
- t = (TextRows *) malloc(sizeof(TextRows));
-
- if (!t) return NULL;
-
- t->t = NULL;
- t->n = 0;
- t->m = 0;
-
- if (!str) return t;
-
- buf = strdup(str);
-
- if (!buf) return t;
-
- z = strlen(buf); /* length of entire string */
- a = buf; /* pointer to the start of the string */
-
- /* initialize the prefix fields */
-
- if (prefix) {
- prefix_len = strlen(prefix);
- local_prefix = strdup(prefix);
- } else {
- prefix_len = 0;
- local_prefix = NULL;
- }
-
- /* adjust the max width for any prefix */
-
- w = width - prefix_len;
-
- do {
- /*
- * if the string will fit on one line, point b to the end of the
- * string
- */
-
- if (z < w) b = a + z;
-
- /*
- * if the string won't fit on one line, move b to where the
- * end of the line should be, and then move b back until we
- * find a space; if we don't find a space before we back b all
- * the way up to a, just assign b to where the line should end.
- */
-
- else {
- b = a + w;
-
- if (word_boundary) {
- while ((b >= a) && (!isspace(*b))) b--;
- if (b <= a) b = a + w;
- }
- }
-
- /* look for any newline between a and b, and move b to it */
-
- for (c = a; c < b; c++) if (*c == '\n') { b = c; break; }
-
- /*
- * copy the string that starts at a and ends at b, prepending
- * with a prefix, if present
- */
-
- len = b-a;
- len += prefix_len;
- line = (char *) malloc(len+1);
- if (local_prefix) strncpy(line, local_prefix, prefix_len);
- strncpy(line + prefix_len, a, len - prefix_len);
- line[len] = '\0';
-
- /* append the new line to the array of text rows */
-
- t->t = (char **) realloc(t->t, sizeof(char *) * (t->n + 1));
- t->t[t->n] = line;
- t->n++;
-
- if (t->m < len) t->m = len;
-
- /*
- * adjust the length of the string and move the pointer to the
- * beginning of the new line
- */
-
- z -= (b - a + 1);
- a = b + 1;
-
- /* move to the first non whitespace character (excluding newlines) */
-
- if (word_boundary && isspace(*b)) {
- while ((z) && (isspace(*a)) && (*a != '\n')) a++, z--;
- } else {
- if (!isspace(*b)) z++, a--;
- }
-
- if (local_prefix) {
- for (i = 0; i < prefix_len; i++) local_prefix[i] = ' ';
- }
-
- } while (z > 0);
-
- if (local_prefix) free(local_prefix);
- free(buf);
-
- return t;
-}
-
-
-/*
- * nv_text_rows_append() - append the given msg to the existing TextRows
- */
-
-void nv_text_rows_append(TextRows *t, const char *msg)
-{
- int len;
-
- t->t = realloc(t->t, sizeof(char *) * (t->n + 1));
-
- if (msg) {
- t->t[t->n] = strdup(msg);
- len = strlen(msg);
- if (t->m < len) t->m = len;
- } else {
- t->t[t->n] = NULL;
- }
-
- t->n++;
-}
-
-/*
- * nv_concat_text_rows() - concatenate two text rows, storing the
- * result in t0
- */
-
-void nv_concat_text_rows(TextRows *t0, TextRows *t1)
-{
- int n, i;
-
- n = t0->n + t1->n;
-
- t0->t = realloc(t0->t, sizeof(char *) * n);
-
- for (i = 0; i < t1->n; i++) {
- t0->t[i + t0->n] = strdup(t1->t[i]);
- }
-
- t0->m = NV_MAX(t0->m, t1->m);
- t0->n = n;
-
-} /* nv_concat_text_rows() */
-
-
-/*
- * nv_free_text_rows() - free the TextRows data structure allocated by
- * nv_format_text_rows()
- */
-
-void nv_free_text_rows(TextRows *t)
-{
- int i;
-
- if (!t) return;
- for (i = 0; i < t->n; i++) free(t->t[i]);
- if (t->t) free(t->t);
- free(t);
-
-} /* nv_free_text_rows() */
-
-
-/****************************************************************************/
-/* printing helper functions */
-/****************************************************************************/
-
-#define DEFAULT_WIDTH 75
-
-static unsigned short __terminal_width = 0;
-
-/*
- * reset_current_terminal_width() - if new_val is zero, then use the
- * TIOCGWINSZ ioctl to get the current width of the terminal, and
- * assign it the value to __terminal_width. If the ioctl fails, use a
- * hardcoded constant. If new_val is non-zero, then use new_val.
- */
-
-void reset_current_terminal_width(unsigned short new_val)
-{
- struct winsize ws;
-
- if (new_val) {
- __terminal_width = new_val;
- return;
- }
-
- if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
- __terminal_width = DEFAULT_WIDTH;
- } else {
- __terminal_width = ws.ws_col - 1;
- }
-}
-
-/*
- * Call silence_fmt(1) to turn fmtout(), fmtoutp() and format() into noops.
- */
-static int __silent = 0;
-
-void silence_fmt(int val)
-{
- __silent = val;
-}
-
-
-static void vformat(FILE *stream, const int wb,
- const char *prefix, const char *buf)
-{
- int i;
- TextRows *t;
-
- if (!__terminal_width) reset_current_terminal_width(0);
-
- 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);
-}
-
-
-#define NV_VFORMAT(stream, wb, prefix, fmt) \
-do { \
- char *buf; \
- NV_VSNPRINTF(buf, fmt); \
- vformat(stream, wb, prefix, buf); \
- free (buf); \
-} while(0)
-
-
-void fmtout(const char *fmt, ...)
-{
- if (__silent > 0) {
- return;
- }
- NV_VFORMAT(stdout, TRUE, NULL, fmt);
-}
-
-
-void fmtoutp(const char *prefix, const char *fmt, ...)
-{
- if (__silent > 0) {
- return;
- }
- NV_VFORMAT(stdout, TRUE, prefix, fmt);
-}
-
-
-void fmterr(const char *fmt, ...)
-{
- vformat(stderr, 0, NULL, "");
- NV_VFORMAT(stderr, TRUE, "ERROR: ", fmt);
- vformat(stderr, 0, NULL, "");
-}
-
-
-void fmtwarn(const char *fmt, ...)
-{
- vformat(stderr, 0, NULL, "");
- NV_VFORMAT(stderr, TRUE, "WARNING: ", fmt);
- vformat(stderr, 0, NULL, "");
-}
-
-
-void fmt(FILE *stream, const char *prefix, const char *fmt, ...)
-{
- if (__silent > 0) {
- return;
- }
- NV_VFORMAT(stream, TRUE, prefix, fmt);
-}
-
-
/*
* Read from the given FILE stream until a newline, EOF, or nul
* terminator is encountered, writing data into a growable buffer.
diff --git a/common-utils/common-utils.h b/common-utils/common-utils.h
index e9d505e..3db71b6 100644
--- a/common-utils/common-utils.h
+++ b/common-utils/common-utils.h
@@ -22,6 +22,8 @@
#include <sys/types.h>
#include <stdint.h>
+#include "msg.h"
+
#if !defined(TRUE)
#define TRUE 1
#endif
@@ -38,32 +40,6 @@
#define TAB " "
#define BIGTAB " "
-#define VERBOSITY_NONE 0 /* nothing */
-#define VERBOSITY_ERROR 1 /* errors only */
-#define VERBOSITY_DEPRECATED 2 /* errors, deprecation messages and warnings */
-#define VERBOSITY_WARNING 3 /* errors and warnings */
-#define VERBOSITY_ALL 4 /* errors, warnings and other info */
-
-#define VERBOSITY_DEFAULT VERBOSITY_ERROR
-
-/*
- * Define a printf format attribute macro. This definition is based on the one
- * from Xfuncproto.h, available in the 'xproto' package at
- * http://xorg.freedesktop.org/releases/individual/proto/
- */
-
-#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)
-# define NV_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y)))
-#else /* not gcc >= 2.3 */
-# define NV_ATTRIBUTE_PRINTF(x,y)
-#endif
-
-typedef struct {
- char **t; /* the text rows */
- int n; /* number of rows */
- int m; /* maximum row length */
-} TextRows;
-
void *nvalloc(size_t size);
char *nvstrcat(const char *str, ...);
void *nvrealloc(void *ptr, size_t size);
@@ -79,22 +55,6 @@ void nvfree(void *s);
char *tilde_expansion(const char *str);
char *nv_prepend_to_string_list(char *list, const char *item, const char *delim);
-TextRows *nv_format_text_rows(const char *prefix,
- const char *str,
- int width, int word_boundary);
-void nv_text_rows_append(TextRows *t, const char *msg);
-void nv_concat_text_rows(TextRows *t0, TextRows *t1);
-void nv_free_text_rows(TextRows *t);
-
-void reset_current_terminal_width(unsigned short new_val);
-
-void silence_fmt(int val);
-void fmtout(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
-void fmtoutp(const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
-void fmterr(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
-void fmtwarn(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
-void fmt(FILE *stream, const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(3, 4);
-
char *fget_next_line(FILE *fp, int *eof);
int nv_open(const char *pathname, int flags, mode_t mode);
@@ -107,51 +67,6 @@ char *nv_trim_space(char *string);
char *nv_trim_char(char *string, char trim);
char *nv_trim_char_strict(char *string, char trim);
-/*
- * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is
- * correct for differing semantics of the vsnprintf() return value:
- *
- * -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)
- *
- * This macro allocates memory for buf; the caller should free it when
- * done.
- */
-
-#define NV_FMT_BUF_LEN 256
-
-#define NV_VSNPRINTF(buf, fmt) \
-do { \
- if (!fmt) { \
- (buf) = NULL; \
- } else { \
- va_list ap; \
- int len, current_len = NV_FMT_BUF_LEN; \
- \
- while (1) { \
- (buf) = nvalloc(current_len); \
- \
- 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_FMT_BUF_LEN; \
- } \
- \
- nvfree(buf); \
- } \
- } \
-} while (0)
-
#if defined(__GNUC__)
# define NV_INLINE __inline__
#else
diff --git a/common-utils/gen-manpage-opts-helper.c b/common-utils/gen-manpage-opts-helper.c
index 532015d..c05ef38 100644
--- a/common-utils/gen-manpage-opts-helper.c
+++ b/common-utils/gen-manpage-opts-helper.c
@@ -17,16 +17,18 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
+#include <stdlib.h>
#include "nvgetopt.h"
#include "gen-manpage-opts-helper.h"
+#include "common-utils.h"
static void print_option(const NVGetoptOption *o)
{
char scratch[64], *s;
int j, len;
- int italics, bold, omitWhiteSpace;
+ int italics, bold, omitWhiteSpace, firstchar;
/* if we are going to need the argument, process it now */
if (o->flags & NVGETOPT_HAS_ARGUMENT) {
@@ -88,13 +90,15 @@ static void print_option(const NVGetoptOption *o)
* '&' : toggles italics on and off
* '^' : toggles bold on and off
* '-' : is backslashified: "\-"
+ * '.' : must not be the first character of a line
*
- * Whitespace is omitted when italics or bold is on
+ * Trailing whitespace is omitted when italics or bold is on
*/
- italics = 0;
- bold = 0;
- omitWhiteSpace = 0;
+ italics = FALSE;
+ bold = FALSE;
+ omitWhiteSpace = FALSE;
+ firstchar = TRUE;
for (s = o->description; s && *s; s++) {
@@ -107,6 +111,7 @@ static void print_option(const NVGetoptOption *o)
}
omitWhiteSpace = italics;
italics = !italics;
+ firstchar = TRUE;
break;
case '^':
if (bold) {
@@ -116,19 +121,33 @@ static void print_option(const NVGetoptOption *o)
}
omitWhiteSpace = bold;
bold = !bold;
+ firstchar = TRUE;
break;
case '-':
printf("\\-");
- omitWhiteSpace = 0;
+ omitWhiteSpace = FALSE;
+ firstchar = FALSE;
break;
case ' ':
if (!omitWhiteSpace) {
printf(" ");
+ firstchar = FALSE;
}
break;
+ case '.':
+ if (firstchar) {
+ fprintf(stderr, "Error: *roff can't start a line with '.' "
+ "If you used '&' or '^' to format text in the "
+ "description of the '%s' option, please add some "
+ "text before the end of the sentence, so that a "
+ "valid manpage can be generated.\n", o->name);
+ exit(1);
+ }
+ /* fall through */
default:
printf("%c", *s);
- omitWhiteSpace = 0;
+ omitWhiteSpace = FALSE;
+ firstchar = FALSE;
break;
}
}
diff --git a/common-utils/msg.c b/common-utils/msg.c
new file mode 100644
index 0000000..cdd3c4f
--- /dev/null
+++ b/common-utils/msg.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#if defined(__sun)
+#include <sys/termios.h>
+#endif
+
+#include "msg.h"
+#include "common-utils.h"
+
+
+/*
+ * verbosity, controls output of errors, warnings and other
+ * information.
+ */
+
+static NvVerbosity __verbosity = NV_VERBOSITY_DEFAULT;
+
+NvVerbosity nv_get_verbosity()
+{
+ return __verbosity;
+}
+
+void nv_set_verbosity(NvVerbosity level)
+{
+ __verbosity = level;
+}
+
+
+/****************************************************************************/
+/* Formatted I/O functions */
+/****************************************************************************/
+
+#define DEFAULT_WIDTH 75
+
+static unsigned short __terminal_width = 0;
+
+/*
+ * reset_current_terminal_width() - if new_val is zero, then use the
+ * TIOCGWINSZ ioctl to get the current width of the terminal, and
+ * assign it the value to __terminal_width. If the ioctl fails, use a
+ * hardcoded constant. If new_val is non-zero, then use new_val.
+ */
+
+void reset_current_terminal_width(unsigned short new_val)
+{
+ struct winsize ws;
+
+ if (new_val) {
+ __terminal_width = new_val;
+ return;
+ }
+
+ if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
+ __terminal_width = DEFAULT_WIDTH;
+ } else {
+ __terminal_width = ws.ws_col - 1;
+ }
+}
+
+
+static void format(FILE *stream, const char *prefix, const char *buf,
+ const int whitespace)
+{
+ int i;
+ TextRows *t;
+
+ if (!__terminal_width) reset_current_terminal_width(0);
+
+ t = nv_format_text_rows(prefix, buf, __terminal_width, whitespace);
+
+ for (i = 0; i < t->n; i++) fprintf(stream, "%s\n", t->t[i]);
+
+ nv_free_text_rows(t);
+}
+
+
+#define NV_FORMAT(stream, prefix, fmt, whitespace) \
+do { \
+ char *buf; \
+ NV_VSNPRINTF(buf, fmt); \
+ format(stream, prefix, buf, whitespace); \
+ free (buf); \
+} while(0)
+
+
+/*
+ * nv_error_msg() - print an error message, nicely formatted using the
+ * format() function.
+ *
+ * This function should be used for all errors.
+ */
+
+void nv_error_msg(const char *fmt, ...)
+{
+ if (__verbosity < NV_VERBOSITY_ERROR) return;
+
+ format(stderr, NULL, "", TRUE);
+ NV_FORMAT(stderr, "ERROR: ", fmt, TRUE);
+ format(stderr, NULL, "", TRUE);
+} /* nv_error_msg() */
+
+
+/*
+ * nv_deprecated_msg() - print a deprecation message, nicely formatted using
+ * the format() function.
+ *
+ * This function should be used for all deprecation messages.
+ */
+
+void nv_deprecated_msg(const char *fmt, ...)
+{
+ if (__verbosity < NV_VERBOSITY_DEPRECATED) return;
+
+ format(stderr, NULL, "", TRUE);
+ NV_FORMAT(stderr, "DEPRECATED: ", fmt, TRUE);
+ format(stderr, NULL, "", TRUE);
+}
+
+
+/*
+ * nv_warning_msg() - print a warning message, nicely formatted using
+ * the format() function.
+ *
+ * This function should be used for all warnings.
+ */
+
+void nv_warning_msg(const char *fmt, ...)
+{
+ if (__verbosity < NV_VERBOSITY_WARNING) return;
+
+ format(stderr, NULL, "", TRUE);
+ NV_FORMAT(stderr, "WARNING: ", fmt, TRUE);
+ format(stderr, NULL, "", TRUE);
+} /* nv_warning_msg() */
+
+
+/*
+ * nv_info_msg() - print an info message, nicely formatted using
+ * the format() function.
+ *
+ * This function should be used to display verbose information.
+ */
+
+void nv_info_msg(const char *prefix, const char *fmt, ...)
+{
+ if (__verbosity < NV_VERBOSITY_ALL) return;
+
+ NV_FORMAT(stdout, prefix, fmt, TRUE);
+} /* nv_info_msg() */
+
+
+/*
+ * nv_info_msg_to_file() - Prints the message, just like nv_info_msg()
+ * using format() the difference is, it prints to any stream defined by
+ * the corresponding argument.
+ */
+
+void nv_info_msg_to_file(FILE *stream, const char *prefix, const char *fmt, ...)
+{
+ if (__verbosity < NV_VERBOSITY_ALL) return;
+
+ NV_FORMAT(stream, prefix, fmt, TRUE);
+} /* nv_info_msg_to_file() */
+
+
+/*
+ * nv_msg() - print a message, nicely formatted using the format()
+ * function.
+ *
+ * This function should be used to display messages independent
+ * of the verbosity level.
+ */
+
+void nv_msg(const char *prefix, const char *fmt, ...)
+{
+ NV_FORMAT(stdout, prefix, fmt, TRUE);
+} /* nv_msg() */
+
+
+/*
+ * nv_msg_preserve_whitespace() - Prints the message, just like nv_msg()
+ * using format(), the difference is, whitespace characters are not
+ * skipped during the text processing.
+ */
+
+void nv_msg_preserve_whitespace(const char *prefix, const char *fmt, ...)
+{
+ NV_FORMAT(stdout, prefix, fmt, FALSE);
+} /* nv_msg_preserve_whitespace() */
+
+
+/*
+ * XXX gcc's '-ansi' option causes vsnprintf to not be defined, so
+ * declare the prototype here.
+ */
+
+#if defined(__STRICT_ANSI__)
+int vsnprintf(char *str, size_t size, const char *format,
+ va_list ap);
+#endif
+
+
+/****************************************************************************/
+/* TextRows helper functions */
+/****************************************************************************/
+
+/*
+ * nv_format_text_rows() - this function breaks the given string str
+ * into some number of rows, where each row is not longer than the
+ * specified width.
+ *
+ * If prefix is non-NULL, the first line is prepended with the prefix,
+ * and subsequent lines are indented to line up with the prefix.
+ *
+ * If word_boundary is TRUE, then attempt to only break lines on
+ * boundaries between words.
+ */
+
+TextRows *nv_format_text_rows(const char *prefix, const char *str, int width,
+ int word_boundary)
+{
+ int len, prefix_len, z, w, i;
+ char *line, *buf, *local_prefix, *a, *b, *c;
+ TextRows *t;
+
+ /* initialize the TextRows structure */
+
+ t = (TextRows *) malloc(sizeof(TextRows));
+
+ if (!t) return NULL;
+
+ t->t = NULL;
+ t->n = 0;
+ t->m = 0;
+
+ if (!str) return t;
+
+ buf = strdup(str);
+
+ if (!buf) return t;
+
+ z = strlen(buf); /* length of entire string */
+ a = buf; /* pointer to the start of the string */
+
+ /* initialize the prefix fields */
+
+ if (prefix) {
+ prefix_len = strlen(prefix);
+ local_prefix = strdup(prefix);
+ } else {
+ prefix_len = 0;
+ local_prefix = NULL;
+ }
+
+ /* adjust the max width for any prefix */
+
+ w = width - prefix_len;
+
+ do {
+ /*
+ * if the string will fit on one line, point b to the end of the
+ * string
+ */
+
+ if (z < w) b = a + z;
+
+ /*
+ * if the string won't fit on one line, move b to where the
+ * end of the line should be, and then move b back until we
+ * find a space; if we don't find a space before we back b all
+ * the way up to a, just assign b to where the line should end.
+ */
+
+ else {
+ b = a + w;
+
+ if (word_boundary) {
+ while ((b >= a) && (!isspace(*b))) b--;
+ if (b <= a) b = a + w;
+ }
+ }
+
+ /* look for any newline between a and b, and move b to it */
+
+ for (c = a; c < b; c++) if (*c == '\n') { b = c; break; }
+
+ /*
+ * copy the string that starts at a and ends at b, prepending
+ * with a prefix, if present
+ */
+
+ len = b-a;
+ len += prefix_len;
+ line = (char *) malloc(len+1);
+ if (local_prefix) strncpy(line, local_prefix, prefix_len);
+ strncpy(line + prefix_len, a, len - prefix_len);
+ line[len] = '\0';
+
+ /* append the new line to the array of text rows */
+
+ t->t = (char **) realloc(t->t, sizeof(char *) * (t->n + 1));
+ t->t[t->n] = line;
+ t->n++;
+
+ if (t->m < len) t->m = len;
+
+ /*
+ * adjust the length of the string and move the pointer to the
+ * beginning of the new line
+ */
+
+ z -= (b - a + 1);
+ a = b + 1;
+
+ /* move to the first non whitespace character (excluding newlines) */
+
+ if (word_boundary && isspace(*b)) {
+ while ((z) && (isspace(*a)) && (*a != '\n')) a++, z--;
+ } else {
+ if (!isspace(*b)) z++, a--;
+ }
+
+ if (local_prefix) {
+ for (i = 0; i < prefix_len; i++) local_prefix[i] = ' ';
+ }
+
+ } while (z > 0);
+
+ if (local_prefix) free(local_prefix);
+ free(buf);
+
+ return t;
+}
+
+
+/*
+ * nv_text_rows_append() - append the given msg to the existing TextRows
+ */
+
+void nv_text_rows_append(TextRows *t, const char *msg)
+{
+ int len;
+
+ t->t = realloc(t->t, sizeof(char *) * (t->n + 1));
+
+ if (msg) {
+ t->t[t->n] = strdup(msg);
+ len = strlen(msg);
+ if (t->m < len) t->m = len;
+ } else {
+ t->t[t->n] = NULL;
+ }
+
+ t->n++;
+}
+
+/*
+ * nv_concat_text_rows() - concatenate two text rows, storing the
+ * result in t0
+ */
+
+void nv_concat_text_rows(TextRows *t0, TextRows *t1)
+{
+ int n, i;
+
+ n = t0->n + t1->n;
+
+ t0->t = realloc(t0->t, sizeof(char *) * n);
+
+ for (i = 0; i < t1->n; i++) {
+ t0->t[i + t0->n] = strdup(t1->t[i]);
+ }
+
+ t0->m = NV_MAX(t0->m, t1->m);
+ t0->n = n;
+
+} /* nv_concat_text_rows() */
+
+
+/*
+ * nv_free_text_rows() - free the TextRows data structure allocated by
+ * nv_format_text_rows()
+ */
+
+void nv_free_text_rows(TextRows *t)
+{
+ int i;
+
+ if (!t) return;
+ for (i = 0; i < t->n; i++) free(t->t[i]);
+ if (t->t) free(t->t);
+ free(t);
+
+} /* nv_free_text_rows() */
+
diff --git a/common-utils/msg.h b/common-utils/msg.h
new file mode 100644
index 0000000..5e32c19
--- /dev/null
+++ b/common-utils/msg.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef __MSG_H__
+#define __MSG_H__
+
+#include <stdarg.h>
+#include <stdio.h>
+
+
+/*
+ * Define a printf format attribute macro. This definition is based on the one
+ * from Xfuncproto.h, available in the 'xproto' package at
+ * http://xorg.freedesktop.org/releases/individual/proto/
+ */
+
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)
+# define NV_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y)))
+#else /* not gcc >= 2.3 */
+# define NV_ATTRIBUTE_PRINTF(x,y)
+#endif
+
+
+/*
+ * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is
+ * correct for differing semantics of the vsnprintf() return value:
+ *
+ * -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)
+ *
+ * This macro allocates memory for buf; the caller should free it when
+ * done.
+ */
+
+#define NV_FMT_BUF_LEN 256
+
+#define NV_VSNPRINTF(buf, fmt) \
+do { \
+ if (!fmt) { \
+ (buf) = NULL; \
+ } else { \
+ va_list ap; \
+ int len, current_len = NV_FMT_BUF_LEN; \
+ \
+ while (1) { \
+ (buf) = nvalloc(current_len); \
+ \
+ 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_FMT_BUF_LEN; \
+ } \
+ \
+ nvfree(buf); \
+ } \
+ } \
+} while (0)
+
+
+/*
+ * verbosity, controls output of errors, warnings and other
+ * information.
+ */
+
+typedef enum {
+ NV_VERBOSITY_NONE = 0, /* no errors, warnings or info */
+ NV_VERBOSITY_ERROR, /* errors only */
+ NV_VERBOSITY_DEPRECATED, /* errors and deprecation messages */
+ NV_VERBOSITY_WARNING, /* errors and all warnings */
+ NV_VERBOSITY_ALL, /* errors, all warnings and other info */
+ NV_VERBOSITY_DEFAULT = NV_VERBOSITY_ALL
+} NvVerbosity;
+
+NvVerbosity nv_get_verbosity(void);
+void nv_set_verbosity(NvVerbosity level);
+
+
+/*
+ * Formatted I/O functions
+ */
+
+void reset_current_terminal_width(unsigned short new_val);
+
+void nv_error_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
+void nv_deprecated_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
+void nv_warning_msg(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
+void nv_info_msg(const char *prefix,
+ const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
+void nv_info_msg_to_file(FILE *stream,
+ const char *prefix,
+ const char *fmt, ...) NV_ATTRIBUTE_PRINTF(3, 4);
+void nv_msg(const char *prefix, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
+void nv_msg_preserve_whitespace(const char *prefix,
+ const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
+
+
+/*
+ * TextRows structure and helper functions
+ */
+
+typedef struct {
+ char **t; /* the text rows */
+ int n; /* number of rows */
+ int m; /* maximum row length */
+} TextRows;
+
+TextRows *nv_format_text_rows(const char *prefix, const char *str, int width,
+ int word_boundary);
+void nv_text_rows_append(TextRows *t, const char *msg);
+void nv_concat_text_rows(TextRows *t0, TextRows *t1);
+void nv_free_text_rows(TextRows *t);
+
+
+#endif /* __MSG_H__ */
diff --git a/common-utils/src.mk b/common-utils/src.mk
index 12ba143..6dbed7a 100644
--- a/common-utils/src.mk
+++ b/common-utils/src.mk
@@ -2,9 +2,11 @@
COMMON_UTILS_SRC += nvgetopt.c
COMMON_UTILS_SRC += common-utils.c
+COMMON_UTILS_SRC += msg.c
COMMON_UTILS_EXTRA_DIST += nvgetopt.h
COMMON_UTILS_EXTRA_DIST += common-utils.h
+COMMON_UTILS_EXTRA_DIST += msg.h
COMMON_UTILS_EXTRA_DIST += src.mk
# gen-manpage-opts-helper.c is listed in EXTRA_DIST, rather than SRC,
diff --git a/files.c b/files.c
index 754f2bc..d7ec29d 100644
--- a/files.c
+++ b/files.c
@@ -1196,12 +1196,18 @@ int directory_exists(Options *op, const char *dir)
int confirm_path(Options *op, const char *path)
{
+ const char *choices[2] = {
+ "Create directory",
+ "Abort installation"
+ };
+
/* return TRUE if the path already exists and is a directory */
if (directory_exists(op, path)) return TRUE;
- if (ui_yes_no(op, TRUE, "The directory '%s' does not exist; "
- "create?", path)) {
+ if (ui_multiple_choice(op, choices, 2, 0, "The directory '%s' does not "
+ "exist; would you like to create it, or would you "
+ "prefer to abort installation?", path) == 0) {
if (mkdir_recursive(op, path, 0755)) {
return TRUE;
} else {
@@ -1569,11 +1575,18 @@ int check_for_existing_rpms(Options *op)
nvfree(cmd);
if (ret == 0) {
- if (!ui_yes_no(op, TRUE, "An %s rpm appears to already be "
- "installed on your system. As part of installing "
- "the new driver, this %s rpm will be uninstalled. "
- "Are you sure you want to continue? ('no' will "
- "abort installation)", rpms[i], rpms[i])) {
+
+ const char *choices[2] = {
+ "Continue installation",
+ "Abort installation"
+ };
+
+ if (ui_multiple_choice(op, choices, 2, 0, "An %s rpm appears to "
+ "already be installed on your system. As "
+ "part of installing the new driver, this %s "
+ "rpm will be uninstalled. Are you sure you "
+ "want to continue?",
+ rpms[i], rpms[i]) == 1) {
ui_log(op, "Installation aborted.");
return FALSE;
}
@@ -2175,23 +2188,43 @@ void get_default_prefixes_and_paths(Options *op)
if (op->distro == DEBIAN && !op->compat32_chroot) {
/*
- * Newer versions of Debian have moved to the Ubuntu style of compat32
- * path, so use that if it exists.
+ * Newer versions of Debian install 32-bit compatibility libraries
+ * to dedicated directories that are not part of a chroot structure.
+ * Search for the known paths and use the first one that is found.
*/
- char *default_path = nvstrcat(op->compat32_prefix, "/"
- UBUNTU_DEFAULT_COMPAT32_LIBDIR, NULL);
- struct stat buf;
- if (lstat(default_path, &buf) < 0 || S_ISLNK(buf.st_mode)) {
+
+ char *debian_compat32_paths[] = { DEBIAN_DEFAULT_COMPAT32_LIBDIR,
+ UBUNTU_DEFAULT_COMPAT32_LIBDIR };
+ int i, found = FALSE;
+
+ for (i = 0; i < ARRAY_LEN(debian_compat32_paths); i++) {
+ char *default_path = nvstrcat(op->compat32_prefix, "/",
+ debian_compat32_paths[i], NULL);
+
+ struct stat buf;
+
+ if (lstat(default_path, &buf) == 0 && !S_ISLNK(buf.st_mode)) {
+ /* path exists and is not a symbolic link, so use it */
+ op->compat32_libdir = debian_compat32_paths[i];
+ found = TRUE;
+ }
+
+ nvfree(default_path);
+
+ if (found) {
+ break;
+ }
+ }
+
+ if (!found) {
/*
- * Path doesn't exist or is a symbolic link. Use the compat32
+ * Paths don't exist or are symbolic links. Use the compat32
* chroot path instead.
*/
+
op->compat32_chroot = DEBIAN_DEFAULT_COMPAT32_CHROOT;
- } else {
- /* <prefix>/lib32 exists, so use that */
- op->compat32_libdir = UBUNTU_DEFAULT_COMPAT32_LIBDIR;
}
- nvfree(default_path);
+
}
#endif
diff --git a/install-from-cwd.c b/install-from-cwd.c
index cbb5499..d3fc30c 100644
--- a/install-from-cwd.c
+++ b/install-from-cwd.c
@@ -84,12 +84,18 @@ int install_from_cwd(Options *op)
const char *msg;
int ret;
int ran_pre_install_hook = FALSE;
+ HookScriptStatus res;
static const char edit_your_xf86config[] =
"Please update your XF86Config or xorg.conf file as "
"appropriate; see the file /usr/share/doc/"
"NVIDIA_GLX-1.0/README.txt for details.";
+ const char *choices[2] = {
+ "Continue installation",
+ "Abort installation"
+ };
+
/*
* validate the manifest file in the cwd, and process it, building
* a Package struct
@@ -137,14 +143,26 @@ int install_from_cwd(Options *op)
/* run the distro preinstall hook */
- if (!run_distro_hook(op, "pre-install")) {
- if (!ui_yes_no(op, TRUE,
- "The distribution-provided pre-install script failed! "
- "Continue installation anyway?")) {
+ res = run_distro_hook(op, "pre-install");
+ if (res == HOOK_SCRIPT_FAIL) {
+ if (ui_multiple_choice(op, choices, 2, 0, "The distribution-provided "
+ "pre-install script failed! Are you sure you "
+ "want to continue?") == 1) {
goto failed;
}
+ } else if (res == HOOK_SCRIPT_SUCCESS) {
+ if (ui_multiple_choice(op, choices, 2, 0, "The distribution-provided "
+ "pre-install script completed successfully. If "
+ "this is the first time you have run the "
+ "installer, this script may have helped disable "
+ "Nouveau, but a reboot may be required first. "
+ "Would you like to continue, or would you "
+ "prefer to abort installation to reboot the "
+ "system?") == 1) {
+ goto exit_install;
+ }
+ ran_pre_install_hook = TRUE;
}
- ran_pre_install_hook = TRUE;
/* fail if the nouveau driver is currently in use */
@@ -480,6 +498,13 @@ dkmscatfailed:
int i;
+ /*
+ * make sure the required development tools are present on
+ * this system before trying to link the kernel interface.
+ */
+ if (!check_precompiled_kernel_interface_tools(op)) {
+ return FALSE;
+ }
/*
* we have a prebuilt kernel interface package, so now link the
@@ -560,6 +585,10 @@ int add_this_kernel(Options *op)
if ((p = parse_manifest(op)) == NULL) goto failed;
+ /* make sure we have the development tools */
+
+ if (!check_development_tools(op, p)) goto failed;
+
/* find the kernel header files */
if (!determine_kernel_source_path(op, p)) goto failed;
@@ -634,7 +663,7 @@ static Package *parse_manifest (Options *op)
char *buf, *c, *flag, *tmpstr, *module_suffix = "";
int done, n, line;
int fd, ret, len = 0;
- struct stat stat_buf, entry_stat_buf;
+ struct stat stat_buf;
Package *p;
char *manifest = MAP_FAILED, *ptr;
@@ -775,30 +804,19 @@ static Package *parse_manifest (Options *op)
free(buf);
done = TRUE;
} else {
-
- p->num_entries++;
- n = p->num_entries - 1;
-
- /* extend the PackageEntry array */
-
- if ((p->entries = (PackageEntry *) nvrealloc
- (p->entries, sizeof(PackageEntry) *
- p->num_entries)) == NULL) {
- ui_error(op, "Memory allocation failure.");
- goto fail;
- }
+ PackageEntry entry;
/* initialize the new entry */
- memset(&p->entries[n], 0, sizeof(PackageEntry));
+ memset(&entry, 0, sizeof(PackageEntry));
/* read the file name and permissions */
c = buf;
- p->entries[n].file = read_next_word(buf, &c);
+ entry.file = read_next_word(buf, &c);
- if (!p->entries[n].file) goto invalid_manifest_file;
+ if (!entry.file) goto invalid_manifest_file;
tmpstr = read_next_word(c, &c);
@@ -806,7 +824,7 @@ static Package *parse_manifest (Options *op)
/* translate the mode string into an octal mode */
- ret = mode_string_to_mode(op, tmpstr, &p->entries[n].mode);
+ ret = mode_string_to_mode(op, tmpstr, &entry.mode);
free(tmpstr);
@@ -814,22 +832,21 @@ static Package *parse_manifest (Options *op)
/* every file has a type field */
- p->entries[n].type = FILE_TYPE_NONE;
+ entry.type = FILE_TYPE_NONE;
flag = read_next_word(c, &c);
if (!flag) goto invalid_manifest_file;
- p->entries[n].type = parse_manifest_file_type(flag,
- &p->entries[n].caps);
+ entry.type = parse_manifest_file_type(flag, &entry.caps);
- if (p->entries[n].type == FILE_TYPE_NONE) {
+ if (entry.type == FILE_TYPE_NONE) {
nvfree(flag);
goto invalid_manifest_file;
}
/* if any UVM files have been packaged, set uvm_files_packaged. */
- if (p->entries[n].type == FILE_TYPE_UVM_MODULE_SRC) {
+ if (entry.type == FILE_TYPE_UVM_MODULE_SRC) {
op->uvm_files_packaged = TRUE;
}
@@ -837,16 +854,16 @@ static Package *parse_manifest (Options *op)
/* some libs/symlinks have an arch field */
- p->entries[n].compat_arch = FILE_COMPAT_ARCH_NONE;
+ entry.compat_arch = FILE_COMPAT_ARCH_NONE;
- if (p->entries[n].caps.has_arch) {
+ if (entry.caps.has_arch) {
flag = read_next_word(c, &c);
if (!flag) goto invalid_manifest_file;
if (strcmp(flag, "COMPAT32") == 0)
- p->entries[n].compat_arch = FILE_COMPAT_ARCH_COMPAT32;
+ entry.compat_arch = FILE_COMPAT_ARCH_COMPAT32;
else if (strcmp(flag, "NATIVE") == 0)
- p->entries[n].compat_arch = FILE_COMPAT_ARCH_NATIVE;
+ entry.compat_arch = FILE_COMPAT_ARCH_NATIVE;
else {
nvfree(flag);
goto invalid_manifest_file;
@@ -857,16 +874,16 @@ static Package *parse_manifest (Options *op)
/* some libs/symlinks have a class field */
- p->entries[n].tls_class = FILE_TLS_CLASS_NONE;
+ entry.tls_class = FILE_TLS_CLASS_NONE;
- if (p->entries[n].caps.has_tls_class) {
+ if (entry.caps.has_tls_class) {
flag = read_next_word(c, &c);
if (!flag) goto invalid_manifest_file;
if (strcmp(flag, "CLASSIC") == 0)
- p->entries[n].tls_class = FILE_TLS_CLASS_CLASSIC;
+ entry.tls_class = FILE_TLS_CLASS_CLASSIC;
else if (strcmp(flag, "NEW") == 0)
- p->entries[n].tls_class = FILE_TLS_CLASS_NEW;
+ entry.tls_class = FILE_TLS_CLASS_NEW;
else {
nvfree(flag);
goto invalid_manifest_file;
@@ -877,20 +894,20 @@ static Package *parse_manifest (Options *op)
/* libs and documentation have a path field */
- if (p->entries[n].caps.has_path) {
- p->entries[n].path = read_next_word(c, &c);
- if (!p->entries[n].path) goto invalid_manifest_file;
+ if (entry.caps.has_path) {
+ entry.path = read_next_word(c, &c);
+ if (!entry.path) goto invalid_manifest_file;
} else {
- p->entries[n].path = NULL;
+ entry.path = NULL;
}
/* symlinks have a target */
- if (p->entries[n].caps.is_symlink) {
- p->entries[n].target = read_next_word(c, &c);
- if (!p->entries[n].target) goto invalid_manifest_file;
+ if (entry.caps.is_symlink) {
+ entry.target = read_next_word(c, &c);
+ if (!entry.target) goto invalid_manifest_file;
} else {
- p->entries[n].target = NULL;
+ entry.target = NULL;
}
/*
@@ -899,24 +916,21 @@ static Package *parse_manifest (Options *op)
* 'file' without any leading directory components
*/
- p->entries[n].name = strrchr(p->entries[n].file, '/');
- if (p->entries[n].name) p->entries[n].name++;
+ entry.name = strrchr(entry.file, '/');
+ if (entry.name) entry.name++;
- if (!p->entries[n].name) p->entries[n].name = p->entries[n].file;
-
- /*
- * store the inode and device information, so that we can
- * later recognize it, to avoid accidentally moving it as
- * part of the 'find_conflicting_files' path
- */
+ if (!entry.name) entry.name = entry.file;
- if (stat(p->entries[n].file, &entry_stat_buf) != -1) {
- p->entries[n].inode = entry_stat_buf.st_ino;
- p->entries[n].device = entry_stat_buf.st_dev;
- } else {
- p->entries[n].inode = 0;
- p->entries[n].device = 0;
- }
+ add_package_entry(p,
+ entry.file,
+ entry.path,
+ entry.name,
+ entry.target,
+ entry.dst,
+ entry.type,
+ entry.tls_class,
+ entry.compat_arch,
+ entry.mode);
/* free the line */
@@ -1113,6 +1127,11 @@ static int assisted_module_signing(Options *op, Package *p)
/* The kernel may or may not enforce module signatures; ask the user
* whether to sign the module. */
+ const char *choices[2] = {
+ "Sign the kernel module",
+ "Install without signing"
+ };
+
const char* sb_message = (secureboot == 1) ?
"This system also has UEFI Secure Boot "
"enabled; many distributions enforce "
@@ -1120,13 +1139,15 @@ static int assisted_module_signing(Options *op, Package *p)
"systems when Secure Boot is enabled. " :
"";
- do_sign = ui_yes_no(op, FALSE, "The target kernel has "
- "CONFIG_MODULE_SIG set, which means that it "
- "supports cryptographic signatures on kernel "
- "modules. On some systems, the kernel may "
- "refuse to load modules without a valid "
- "signature from a trusted key. %sWould you like "
- "to sign the NVIDIA kernel module?", sb_message);
+ do_sign = (ui_multiple_choice(op, choices, 2, 1, "The target kernel "
+ "has CONFIG_MODULE_SIG set, which means "
+ "that it supports cryptographic "
+ "signatures on kernel modules. On some "
+ "systems, the kernel may refuse to load "
+ "modules without a valid signature from "
+ "a trusted key. %sWould you like to sign "
+ "the NVIDIA kernel module?",
+ sb_message) == 0);
}
if (!do_sign) {
@@ -1138,11 +1159,18 @@ static int assisted_module_signing(Options *op, Package *p)
/* If we're missing either key, we need to get both from the user. */
if (!op->module_signing_secret_key || !op->module_signing_public_key) {
- generate_keys = !ui_yes_no(op, FALSE, "Do you already have a key pair "
- "which can be used to sign the NVIDIA "
- "kernel module? Answer 'Yes' to use an "
- "existing key pair, or 'No' to generate a "
- "new key pair.");
+
+ const char *choices[2] = {
+ "Use an existing key pair",
+ "Generate a new key pair"
+ };
+
+ generate_keys = (ui_multiple_choice(op, choices, 2, 1, "Would you like "
+ "to sign the NVIDIA kernel module "
+ "with an existing key pair, or "
+ "would you like to generate a new "
+ "one?") == 1);
+
if (generate_keys) {
char *cmdline, *x509_hash;
int ret;
diff --git a/kernel.c b/kernel.c
index ae54df6..082eba2 100644
--- a/kernel.c
+++ b/kernel.c
@@ -171,7 +171,7 @@ int determine_kernel_module_installation_path(Options *op)
static int run_conftest(Options *op, Package *p, const char *args, char **result)
{
- char *CC, *cmd, *arch;
+ char *cmd, *arch;
int ret;
if (result)
@@ -181,13 +181,10 @@ static int run_conftest(Options *op, Package *p, const char *args, char **result
if (!arch)
return FALSE;
- CC = getenv("CC");
- if (!CC) CC = "cc";
-
cmd = nvstrcat("sh \"", p->kernel_module_build_directory,
- "/conftest.sh\" \"", CC, "\" \"", CC, "\" \"", arch, "\" \"",
- op->kernel_source_path, "\" \"", op->kernel_output_path,
- "\" ", args, NULL);
+ "/conftest.sh\" \"", op->utils[CC], "\" \"", op->utils[CC],
+ "\" \"", arch, "\" \"", op->kernel_source_path, "\" \"",
+ op->kernel_output_path, "\" ", args, NULL);
ret = run_command(op, cmd, result, FALSE, 0, TRUE);
nvfree(cmd);
@@ -432,6 +429,11 @@ static int attach_signature(Options *op, Package *p,
char *module_path;
int ret = FALSE, command_ret;
+ const char *choices[2] = {
+ "Install unsigned kernel module",
+ "Abort installation"
+ };
+
ui_log(op, "Attaching module signature to linked kernel module.");
module_path = nvstrcat(p->kernel_module_build_directory, "/",
@@ -456,27 +458,30 @@ static int attach_signature(Options *op, Package *p,
attach_done:
fclose(module_file);
} else {
- ret = ui_yes_no(op, FALSE,
- "A detached signature was included with the "
- "precompiled interface, but opening the linked "
- "kernel module and/or the signature file failed."
- "\n\nThe detached signature will not be added; "
- "would you still like to install the unsigned "
- "kernel module?");
+ ret = (ui_multiple_choice(op, choices, 2, 1,
+ "A detached signature was included with "
+ "the precompiled interface, but opening "
+ "the linked kernel module and/or the "
+ "signature file failed.\n\nThe detached "
+ "signature will not be added; would you "
+ "still like to install the unsigned "
+ "kernel module?") == 0);
}
} else {
- ret = ui_yes_no(op, FALSE,
- "A detached signature was included with the "
- "precompiled interface, but the checksum of the linked "
- "kernel module (%d) did not match the checksum of the "
- "the kernel module for which the detached signature "
- "was generated (%d).\n\nThis can happen if the linker "
- "on the installation target system is not the same as "
- "the linker on the system that built the precompiled "
- "interface.\n\nThe detached signature will not be "
- "added; would you still like to install the unsigned "
- "kernel module?", actual_crc,
- fileInfo->linked_module_crc);
+ ret = (ui_multiple_choice(op, choices, 2, 1,
+ "A detached signature was included with the "
+ "precompiled interface, but the checksum of "
+ "the linked kernel module (%d) did not match "
+ "the checksum of the the kernel module for "
+ "which the detached signature was generated "
+ "(%d).\n\nThis can happen if the linker on "
+ "the installation target system is not the "
+ "same as the linker on the system that built "
+ "the precompiled interface.\n\nThe detached "
+ "signature will not be added; would you "
+ "still like to install the unsigned kernel "
+ "module?", actual_crc,
+ fileInfo->linked_module_crc) == 0);
}
if (ret) {
@@ -584,7 +589,7 @@ static int build_kernel_module_helper(Options *op, const char *dir,
ui_status_begin(op, tmp, "Building");
nvfree(tmp);
- cmd = nvstrcat("cd ", dir, "; make module",
+ cmd = nvstrcat("cd ", dir, "; ", op->utils[MAKE], " module",
" SYSSRC=", op->kernel_source_path,
" SYSOUT=", op->kernel_output_path,
instances, NULL);
@@ -598,11 +603,13 @@ static int build_kernel_module_helper(Options *op, const char *dir,
ui_status_end(op, "Error.");
ui_error(op, "Unable to build the %s kernel module.", module);
/* XXX need more descriptive error message */
+
+ return FALSE;
}
ui_status_end(op, "done.");
- return ret == 0;
+ return TRUE;
}
@@ -633,7 +640,7 @@ static int check_file(Options *op, const char *dir, const char *filename,
int build_kernel_module(Options *op, Package *p)
{
char *result, *cmd;
- int len, ret;
+ int ret;
/*
* touch all the files in the build directory to avoid make time
@@ -661,10 +668,8 @@ int build_kernel_module(Options *op, Package *p)
ui_log(op, "Cleaning kernel module build directory.");
- len = strlen(p->kernel_module_build_directory) + 32;
- cmd = nvalloc(len);
-
- snprintf(cmd, len, "cd %s; make clean", p->kernel_module_build_directory);
+ cmd = nvstrcat("cd ", p->kernel_module_build_directory, "; ",
+ op->utils[MAKE], " clean", NULL);
ret = run_command(op, cmd, &result, TRUE, 0, TRUE);
free(result);
@@ -757,7 +762,7 @@ int sign_kernel_module(Options *op, const char *build_directory,
build_module_instances_parameter = nvstrdup("");
}
- cmd = nvstrcat("cd ", build_directory, "; make module-sign"
+ cmd = nvstrcat("cd ", build_directory, "; ", op->utils[MAKE], " module-sign"
" SYSSRC=", op->kernel_source_path,
" SYSOUT=", op->kernel_output_path,
" MODSECKEY=", op->module_signing_secret_key,
@@ -885,7 +890,7 @@ static int build_kernel_interface_file(Options *op, const char *tmpdir,
nvasprintf(" NV_BUILD_MODULE_INSTANCES=%d", NV_MAX_MODULE_INSTANCES);
}
- cmd = nvstrcat("cd ", tmpdir, "; make ",
+ cmd = nvstrcat("cd ", tmpdir, "; ", op->utils[MAKE], " ",
kernel_interface_filename,
" SYSSRC=", op->kernel_source_path,
" SYSOUT=", op->kernel_output_path,
@@ -1364,21 +1369,28 @@ static int ignore_load_error(Options *op, Package *p,
if (enokey || secureboot || module_sig_force || op->expert) {
if (op->kernel_module_signed) {
- ignore_error = ui_yes_no(op, TRUE,
- "The signed kernel module failed to "
- "load%s because the kernel does not "
- "trust any key which is capable of "
- "verifying the module signature. "
- "Would you like to install the signed "
- "kernel module anyway?\n\nNote that %s"
- "you will not be able to load the "
- "installed module until after a key "
- "that can verify the module signature "
- "is added to a key database that is "
- "trusted by the kernel. This will "
- "likely require rebooting your "
- "computer.", probable_reason,
- signature_related);
+ const char *choices[2] = {
+ "Install signed kernel module",
+ "Abort installation"
+ };
+
+ ignore_error = (ui_multiple_choice(op, choices, 2, 0,
+ "The signed kernel module failed "
+ "to load%s because the kernel "
+ "does not trust any key which is "
+ "capable of verifying the module "
+ "signature. Would you like to "
+ "install the signed kernel module "
+ "anyway?\n\nNote that %syou "
+ "will not be able to load the "
+ "installed module until after a "
+ "key that can verify the module "
+ "signature is added to a key "
+ "database that is trusted by the "
+ "kernel. This will likely "
+ "require rebooting your computer.",
+ probable_reason,
+ signature_related) == 0);
} else {
const char *secureboot_message, *dkms_message;
@@ -1876,11 +1888,16 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
/* If we found one, ask expert users if they really want to use it */
if (info && op->expert) {
- if (!ui_yes_no(op, TRUE, "A precompiled kernel interface for the "
- "kernel '%s' has been found. Would you like to "
- "use this? (answering 'no' will require the "
- "installer to compile the interface)",
- info->description)) {
+ const char *choices[2] = {
+ "Use the precompiled interface",
+ "Compile the interface"
+ };
+
+ if (ui_multiple_choice(op, choices, 2, 0, "A precompiled kernel "
+ "interface for the kernel '%s' has been found. "
+ "Would you like use the precompiled interface, "
+ "or would you like to compile the interface "
+ "instead?", info->description) == 1) {
free_precompiled(info);
info = NULL;
}
@@ -2438,6 +2455,11 @@ int check_cc_version(Options *op, Package *p)
int ret;
Options dummyop;
+ const char *choices[2] = {
+ "Ignore CC version check",
+ "Abort installation"
+ };
+
/*
* If we're building/installing for a different kernel, then we
* can't do the gcc version check (we don't have a /proc/version
@@ -2461,14 +2483,13 @@ int check_cc_version(Options *op, Package *p)
if (ret) return TRUE;
- ret = ui_yes_no(op, TRUE, "The CC version check failed:\n\n%s\n\n"
- "If you know what you are doing and want to "
- "ignore the gcc version check, select \"No\" to "
- "continue installation. Otherwise, select \"Yes\" to "
- "abort installation, set the CC environment variable to "
- "the name of the compiler used to compile your kernel, "
- "and restart installation. Abort now?", result);
-
+ ret = (ui_multiple_choice(op, choices, 2, 1, "The CC version check failed:"
+ "\n\n%s\n\nIf you know what you are doing you "
+ "can either ignore the CC version check and "
+ "continue installation, or abort installation, "
+ "set the CC environment variable to the name of "
+ "the compiler used to compile your kernel, and "
+ "restart installation.", result) == 1);
nvfree(result);
if (!ret) setenv("IGNORE_CC_MISMATCH", "1", 1);
diff --git a/makeself-help-script.c b/makeself-help-script.c
index 47f8a9a..605953a 100644
--- a/makeself-help-script.c
+++ b/makeself-help-script.c
@@ -11,6 +11,7 @@
#include "nvidia-installer.h"
#include "nvgetopt.h"
#include "option_table.h"
+#include "msg.h"
static void print_usage(char **argv)
{
@@ -20,9 +21,9 @@ static void print_usage(char **argv)
static void print_help_helper(const char *name, const char *description)
{
- fmtoutp(TAB, name);
- fmtoutp(BIGTAB, description);
- fmtout("");
+ nv_info_msg(TAB, name);
+ nv_info_msg(BIGTAB, description);
+ nv_info_msg(NULL, "");
}
int main(int argc, char **argv)
@@ -37,7 +38,7 @@ int main(int argc, char **argv)
/*
* We are printing help text for use by makeself.sh; we do not
* want this formatted to the width of the current terminal, so
- * hardcode the width used by fmtout() to 65.
+ * hardcode the width used by nv_info_msg() to 65.
*/
reset_current_terminal_width(65);
diff --git a/manifest.c b/manifest.c
index b8a304d..39439fe 100644
--- a/manifest.c
+++ b/manifest.c
@@ -173,7 +173,8 @@ void get_installable_file_type_list(
continue;
}
- if ((type == FILE_TYPE_KERNEL_MODULE_SRC) &&
+ if (((type == FILE_TYPE_KERNEL_MODULE_SRC) ||
+ (type == FILE_TYPE_UVM_MODULE_SRC)) &&
op->no_kernel_module_source) {
continue;
}
diff --git a/misc.c b/misc.c
index b310826..2715d25 100644
--- a/misc.c
+++ b/misc.c
@@ -54,7 +54,6 @@
#include "manifest.h"
static int check_symlink(Options*, const char*, const char*, const char*);
-static int check_file(Options*, const char*, const mode_t, const uint32);
/*
@@ -158,16 +157,22 @@ int check_runlevel(Options *op)
nvfree(data);
if (runlevel == 's' || runlevel == 'S' || runlevel == '1') {
- ret = ui_yes_no(op, TRUE, "You appear to be running in runlevel 1; "
- "this may cause problems. For example: some "
- "distributions that use devfs do not run the devfs "
- "daemon in runlevel 1, making it difficult for "
- "`nvidia-installer` to correctly setup the kernel "
- "module configuration files. It is recommended "
- "that you quit installation now and switch to "
- "runlevel 3 (`telinit 3`) before installing.\n\n"
- "Quit installation now? (select 'No' to continue "
- "installation)");
+
+ const char *choices[2] = {
+ "Continue installation",
+ "Abort installation"
+ };
+
+ ret = (ui_multiple_choice(op, choices, 2, 1, "You appear to be running "
+ "in runlevel 1; this may cause problems. "
+ "For example: some distributions that use "
+ "devfs do not run the devfs daemon in "
+ "runlevel 1, making it difficult for "
+ "`nvidia-installer` to correctly setup the "
+ "kernel module configuration files. It is "
+ "recommended that you quit installation now "
+ "and switch to runlevel 3 (`telinit 3`) "
+ "before installing.") == 1);
if (ret) return FALSE;
}
@@ -487,67 +492,84 @@ int read_text_file(const char *filename, char **buf)
* additional directories) for the utilities that the installer will
* need to use. Returns TRUE on success and assigns the util fields
* in the option struct; it returns FALSE on failure.
- *
- * XXX requiring ld may cause problems
*/
#define EXTRA_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/bin/X11"
+/*
+ * Utils list; keep in sync with SystemUtils, SystemOptionalUtils, ModuleUtils
+ * and DevelopUtils enum types
+ */
+
+typedef struct {
+ const char *util;
+ const char *package;
+} Util;
+
+static const Util __utils[] = {
+
+ /* SystemUtils */
+ [LDCONFIG] = { "ldconfig", "glibc" },
+ [LDD] = { "ldd", "glibc" },
+ [GREP] = { "grep", "grep" },
+ [DMESG] = { "dmesg", "util-linux" },
+ [TAIL] = { "tail", "coreutils" },
+ [CUT] = { "cut", "coreutils" },
+ [TR] = { "tr", "coreutils" },
+ [SED] = { "sed", "sed" },
+
+ /* SystemOptionalUtils */
+ [OBJCOPY] = { "objcopy", "binutils" },
+ [CHCON] = { "chcon", "selinux" },
+ [SELINUX_ENABLED] = { "selinuxenabled", "selinux" },
+ [GETENFORCE] = { "getenforce", "selinux" },
+ [EXECSTACK] = { "execstack", "selinux" },
+ [PKG_CONFIG] = { "pkg-config", "pkg-config" },
+ [XSERVER] = { "X", "xserver" },
+ [OPENSSL] = { "openssl", "openssl" },
+
+ /* ModuleUtils */
+ [INSMOD] = { "insmod", "module-init-tools' or 'kmod" },
+ [MODPROBE] = { "modprobe", "module-init-tools' or 'kmod" },
+ [RMMOD] = { "rmmod", "module-init-tools' or 'kmod" },
+ [LSMOD] = { "lsmod", "module-init-tools' or 'kmod" },
+ [DEPMOD] = { "depmod", "module-init-tools' or 'kmod" },
+
+ /* DevelopUtils */
+ [CC] = { "cc", "gcc" },
+ [MAKE] = { "make", "make" },
+ [LD] = { "ld", "binutils" },
+
+};
+
int find_system_utils(Options *op)
{
- /* keep in sync with the SystemUtils enum type */
- const struct { const char *util, *package; } needed_utils[] = {
- { "ldconfig", "glibc" },
- { "ldd", "glibc" },
- { "ld", "binutils" },
- { "objcopy", "binutils" },
- { "grep", "grep" },
- { "dmesg", "util-linux" },
- { "tail", "coreutils" },
- { "cut", "coreutils" },
- { "tr", "coreutils" },
- { "sed", "sed" }
- };
-
- /* keep in sync with the SystemOptionalUtils enum type */
- const struct { const char *util, *package; } optional_utils[] = {
- { "chcon", "selinux" },
- { "selinuxenabled", "selinux" },
- { "getenforce", "selinux" },
- { "execstack", "selinux" },
- { "pkg-config", "pkg-config" },
- { "X", "xserver" },
- { "openssl", "openssl" }
- };
-
- int i, j;
+ int i;
ui_expert(op, "Searching for system utilities:");
/* search the PATH for each utility */
- for (i = 0; i < MAX_SYSTEM_UTILS; i++) {
- op->utils[i] = find_system_util(needed_utils[i].util);
+ for (i = MIN_SYSTEM_UTILS; i < MAX_SYSTEM_UTILS; i++) {
+ op->utils[i] = find_system_util(__utils[i].util);
if (!op->utils[i]) {
ui_error(op, "Unable to find the system utility `%s`; please "
"make sure you have the package '%s' installed. If "
"you do have %s installed, then please check that "
"`%s` is in your PATH.",
- needed_utils[i].util, needed_utils[i].package,
- needed_utils[i].package, needed_utils[i].util);
+ __utils[i].util, __utils[i].package,
+ __utils[i].package, __utils[i].util);
return FALSE;
}
- ui_expert(op, "found `%s` : `%s`",
- needed_utils[i].util, op->utils[i]);
+ ui_expert(op, "found `%s` : `%s`", __utils[i].util, op->utils[i]);
}
- for (j = 0, i = MAX_SYSTEM_UTILS; i < MAX_SYSTEM_OPTIONAL_UTILS; i++, j++) {
-
- op->utils[i] = find_system_util(optional_utils[j].util);
- if (op->utils[i]) {
- ui_expert(op, "found `%s` : `%s`",
- optional_utils[j].util, op->utils[i]);
+ for (i = MIN_SYSTEM_OPTIONAL_UTILS; i < MAX_SYSTEM_OPTIONAL_UTILS; i++) {
+
+ op->utils[i] = find_system_util(__utils[i].util);
+ if (op->utils[i]) {
+ ui_expert(op, "found `%s` : `%s`", __utils[i].util, op->utils[i]);
}
}
@@ -571,30 +593,6 @@ int find_system_utils(Options *op)
} /* find_system_utils() */
-
-typedef struct {
- const char *util;
- const char *package;
-} Util;
-
-/* keep in sync with the ModuleUtils enum type */
-static Util __module_utils[] = {
- { "insmod", "module-init-tools" },
- { "modprobe", "module-init-tools" },
- { "rmmod", "module-init-tools" },
- { "lsmod", "module-init-tools" },
- { "depmod", "module-init-tools" },
-};
-
-/* keep in sync with the ModuleUtils enum type */
-static Util __module_utils_linux24[] = {
- { "insmod", "modutils" },
- { "modprobe", "modutils" },
- { "rmmod", "modutils" },
- { "lsmod", "modutils" },
- { "depmod", "modutils" },
-};
-
/*
* find_module_utils() - search the $PATH (as well as some common
* additional directories) for the utilities that the installer will
@@ -604,30 +602,25 @@ static Util __module_utils_linux24[] = {
int find_module_utils(Options *op)
{
- int i, j;
- Util *needed_utils = __module_utils;
-
- if (strncmp(get_kernel_name(op), "2.4", 3) == 0)
- needed_utils = __module_utils_linux24;
+ int i;
ui_expert(op, "Searching for module utilities:");
/* search the PATH for each utility */
- for (j=0, i = MAX_SYSTEM_OPTIONAL_UTILS; i < MAX_UTILS; i++, j++) {
- op->utils[i] = find_system_util(needed_utils[j].util);
+ for (i = MIN_MODULE_UTILS; i < MAX_MODULE_UTILS; i++) {
+ op->utils[i] = find_system_util(__utils[i].util);
if (!op->utils[i]) {
ui_error(op, "Unable to find the module utility `%s`; please "
"make sure you have the package '%s' installed. If "
- "you do have %s installed, then please check that "
+ "you do have '%s' installed, then please check that "
"`%s` is in your PATH.",
- needed_utils[j].util, needed_utils[j].package,
- needed_utils[j].package, needed_utils[j].util);
+ __utils[i].util, __utils[i].package,
+ __utils[i].package, __utils[i].util);
return FALSE;
}
- ui_expert(op, "found `%s` : `%s`",
- needed_utils[j].util, op->utils[i]);
+ ui_expert(op, "found `%s` : `%s`", __utils[i].util, op->utils[i]);
};
return TRUE;
@@ -744,18 +737,31 @@ int check_proc_modprobe_path(Options *op)
* to build custom kernel interfaces are available.
*/
+static int check_development_tool(Options *op, int idx)
+{
+ if (!op->utils[idx]) {
+ ui_error(op, "Unable to find the development tool `%s` in "
+ "your path; please make sure that you have the "
+ "package '%s' installed. If %s is installed on your "
+ "system, then please check that `%s` is in your "
+ "PATH.",
+ __utils[idx].util, __utils[idx].package,
+ __utils[idx].package, __utils[idx].util);
+ return FALSE;
+ }
+
+ ui_expert(op, "found `%s` : `%s`", __utils[idx].util, op->utils[idx]);
+
+ return TRUE;
+}
+
int check_development_tools(Options *op, Package *p)
{
-#define MAX_TOOLS 2
- const struct { char *tool, *package; } needed_tools[] = {
- { "cc", "gcc" },
- { "make", "make" }
- };
int i, ret;
- char *tool, *cmd, *CC, *result;
+ char *cmd, *result;
- CC = getenv("CC");
+ op->utils[CC] = getenv("CC");
ui_expert(op, "Checking development tools:");
@@ -768,20 +774,13 @@ int check_development_tools(Options *op, Package *p)
* checked below.
*/
- for (i = (CC != NULL) ? 1 : 0; i < MAX_TOOLS; i++) {
- tool = find_system_util(needed_tools[i].tool);
- if (!tool) {
- ui_error(op, "Unable to find the development tool `%s` in "
- "your path; please make sure that you have the "
- "package '%s' installed. If %s is installed on your "
- "system, then please check that `%s` is in your "
- "PATH.",
- needed_tools[i].tool, needed_tools[i].package,
- needed_tools[i].package, needed_tools[i].tool);
+ for (i = (op->utils[CC] != NULL) ? MIN_DEVELOP_UTILS + 1 : MIN_DEVELOP_UTILS;
+ i < MAX_DEVELOP_UTILS; i++) {
+
+ op->utils[i] = find_system_util(__utils[i].util);
+ if (!check_development_tool(op, i)) {
return FALSE;
}
-
- ui_expert(op, "found `%s` : `%s`", needed_tools[i].tool, tool);
}
/*
@@ -795,12 +794,12 @@ int check_development_tools(Options *op, Package *p)
return FALSE;
}
- if (!CC) CC = "cc";
+ if (!op->utils[CC]) op->utils[CC] = "cc";
- ui_log(op, "Performing CC sanity check with CC=\"%s\".", CC);
+ ui_log(op, "Performing CC sanity check with CC=\"%s\".", op->utils[CC]);
cmd = nvstrcat("sh ", p->kernel_module_build_directory,
- "/conftest.sh ", CC, " ", CC, " ",
+ "/conftest.sh ", op->utils[CC], " ", op->utils[CC], " ",
"DUMMY_SOURCE DUMMY_OUTPUT ",
"cc_sanity_check just_msg", NULL);
@@ -820,6 +819,23 @@ int check_development_tools(Options *op, Package *p)
/*
+ * check_precompiled_kernel_interface_tools() - check if the development tools
+ * needed to link precompiled kernel interfaces are available.
+ */
+
+int check_precompiled_kernel_interface_tools(Options *op)
+{
+ /*
+ * If precompiled info has been found we only need to check for
+ * a linker
+ */
+ op->utils[LD] = find_system_util(__utils[LD].util);
+ return check_development_tool(op, LD);
+
+} /* check_precompiled_kernel_interface_tools() */
+
+
+/*
* find_system_util() - build a search path and search for the named
* utility. If the utility is found, the fully qualified path to the
* utility is returned. On failure NULL is returned.
@@ -876,11 +892,17 @@ int continue_after_error(Options *op, const char *fmt, ...)
char *msg;
int ret;
+ const char *choices[2] = {
+ "Continue installation",
+ "Abort installation"
+ };
+
NV_VSNPRINTF(msg, fmt);
- ret = ui_yes_no(op, TRUE, "The installer has encountered the following "
- "error during installation: '%s'. Continue anyway? "
- "(\"no\" will abort)?", msg);
+ ret = (ui_multiple_choice(op, choices, 2, 0, "The installer has encountered "
+ "the following error during installation: '%s'. "
+ "Would you like to continue installation anyway?",
+ msg) == 0);
nvfree(msg);
@@ -1172,15 +1194,23 @@ void should_install_compat32_files(Options *op, Package *p)
if (install_compat32_files && (op->compat32_chroot != NULL) &&
access(op->compat32_chroot, F_OK) < 0) {
- install_compat32_files = ui_yes_no(op, FALSE,
- "The NVIDIA 32-bit compatibility libraries are "
- "to be installed relative to the top-level prefix (chroot) "
- "'%s'; however, this directory does not exist. Please "
- "consult your distribution's documentation to confirm the "
- "correct top-level installation prefix for 32-bit "
- "compatiblity libraries.\n\nDo you wish to install the "
- "NVIDIA 32-bit compatibility libraries anyway?",
- op->compat32_chroot);
+
+ const char *choices[2] = {
+ "Install compatibility libraries",
+ "Do not install compatibility libraries"
+ };
+
+ install_compat32_files = (ui_multiple_choice(op, choices, 2, 1,
+ "The NVIDIA 32-bit compatibility libraries "
+ "are to be installed relative to the "
+ "top-level prefix (chroot) '%s'; however, "
+ "this directory does not exist. Please "
+ "consult your distribution's documentation "
+ "to confirm the correct top-level "
+ "installation prefix for 32-bit compatiblity "
+ "libraries.\n\nWould you like to install "
+ "NVIDIA 32-bit compatibility libraries "
+ "anyway?", op->compat32_chroot) == 0);
}
if (!install_compat32_files) {
@@ -1330,7 +1360,8 @@ void check_installed_files_from_package(Options *op, Package *p)
ret = FALSE;
}
} else if (installable_files.types[p->entries[i].type]) {
- if (!check_file(op, p->entries[i].dst, p->entries[i].mode, 0)) {
+ if (!check_installed_file(op, p->entries[i].dst,
+ p->entries[i].mode, 0, ui_warn)) {
ret = FALSE;
}
}
@@ -1400,7 +1431,7 @@ static int check_symlink(Options *op, const char *target, const char *link,
* unprelink() - attempt to run `prelink -u` on a file to restore it to
* its pre-prelinked state.
*/
-int unprelink(Options *op, const char *filename)
+static int unprelink(Options *op, const char *filename)
{
char *cmd;
int ret = ENOENT;
@@ -1437,33 +1468,39 @@ int verify_crc(Options *op, const char *filename, unsigned int crc,
/*
- * check_file() - check that the specified installed file exists, has
- * the correct permissions, and has the correct crc.
+ * check_installed_file() - check that the specified installed file exists,
+ * has the correct permissions, and has the correct crc. Takes a function
+ * pointer to either ui_log() or ui_warn() depending on how errors should
+ * be reported.
*
* If anything is incorrect, print a warning and return FALSE,
* otherwise return TRUE.
*/
-static int check_file(Options *op, const char *filename,
- const mode_t mode, const uint32 crc)
+int check_installed_file(Options *op, const char *filename,
+ const mode_t mode, const uint32 crc,
+ ui_message_func *logwarn)
{
struct stat stat_buf;
uint32 actual_crc;
if (lstat(filename, &stat_buf) == -1) {
- ui_warn(op, "Unable to find installed file '%s' (%s).",
+ logwarn(op, "Unable to find installed file '%s' (%s).",
filename, strerror(errno));
return FALSE;
}
if (!S_ISREG(stat_buf.st_mode)) {
- ui_warn(op, "The installed file '%s' is not of the correct filetype.",
+ logwarn(op, "The installed file '%s' is not of the correct filetype.",
filename);
return FALSE;
}
- if ((stat_buf.st_mode & PERM_MASK) != (mode & PERM_MASK)) {
- ui_warn(op, "The installed file '%s' has permissions %04o, but it "
+ /* Don't check the mode if we don't have one: backup log entries for
+ installed files don't preserve the mode. */
+
+ if (mode && ((stat_buf.st_mode & PERM_MASK) != (mode & PERM_MASK))) {
+ logwarn(op, "The installed file '%s' has permissions %04o, but it "
"was installed with permissions %04o.", filename,
(stat_buf.st_mode & PERM_MASK),
(mode & PERM_MASK));
@@ -1474,6 +1511,17 @@ static int check_file(Options *op, const char *filename,
if (!verify_crc(op, filename, crc, &actual_crc)) {
int ret;
+ /* If this is not an ELF file, we should not try to unprelink it. */
+
+ if (get_elf_architecture(filename) == ELF_INVALID_FILE) {
+ logwarn(op, "The installed file '%s' has a different checksum "
+ "(%ul) than when it was installed (%ul).", filename,
+ actual_crc, crc);
+ return FALSE;
+ }
+
+ /* Otherwise, unprelinking may be able to restore the original file. */
+
ui_expert(op, "The installed file '%s' has a different checksum (%ul) "
"than when it was installed (%ul). This may be due to "
"prelinking; attemping `prelink -u %s` to restore the file.",
@@ -1481,24 +1529,27 @@ static int check_file(Options *op, const char *filename,
ret = unprelink(op, filename);
if (ret != 0) {
- ui_warn(op, "The installed file '%s' seems to have changed, but "
+ logwarn(op, "The installed file '%s' seems to have changed, but "
"`prelink -u` failed; unable to restore '%s' to an "
"un-prelinked state.", filename, filename);
return FALSE;
}
if (!verify_crc(op, filename, crc, &actual_crc)) {
- ui_warn(op, "The installed file '%s' has a different checksum "
+ logwarn(op, "The installed file '%s' has a different checksum "
"(%ul) after running `prelink -u` than when it was "
"installed (%ul).",
filename, actual_crc, crc);
return FALSE;
}
+
+ ui_expert(op, "Un-prelinking successful: %s was restored to its "
+ "original state.", filename);
}
return TRUE;
-} /* check_file() */
+}
@@ -2519,7 +2570,7 @@ int run_nvidia_xconfig(Options *op, int restore)
* run_distro_hook() - run a distribution-provided hook script
*/
-int run_distro_hook(Options *op, const char *hook)
+HookScriptStatus run_distro_hook(Options *op, const char *hook)
{
int ret, status, shouldrun = op->run_distro_scripts;
char *cmd = nvstrcat(DISTRO_HOOK_DIRECTORY, hook, NULL);
@@ -2529,14 +2580,13 @@ int run_distro_hook(Options *op, const char *hook)
"Not running distribution-provided %s script %s because "
"--kernel-module-only was specified.",
hook, cmd);
- ret = TRUE;
+ ret = HOOK_SCRIPT_NO_RUN;
goto done;
}
if (access(cmd, X_OK) < 0) {
- /* it's okay if the script doesn't exist or isn't executable */
ui_expert(op, "No distribution %s script found.", hook);
- ret = TRUE;
+ ret = HOOK_SCRIPT_NO_RUN;
goto done;
}
@@ -2551,7 +2601,7 @@ int run_distro_hook(Options *op, const char *hook)
ui_expert(op,
"Not running distribution-provided %s script %s",
hook, cmd);
- ret = TRUE;
+ ret = HOOK_SCRIPT_NO_RUN;
goto done;
}
@@ -2559,7 +2609,7 @@ int run_distro_hook(Options *op, const char *hook)
status = run_command(op, cmd, NULL, TRUE, 0, TRUE);
ui_status_end(op, "done.");
- ret = (status == 0);
+ ret = (status == 0) ? HOOK_SCRIPT_SUCCESS : HOOK_SCRIPT_FAIL;
done:
nvfree(cmd);
diff --git a/misc.h b/misc.h
index fad1c9f..416bebe 100644
--- a/misc.h
+++ b/misc.h
@@ -29,6 +29,19 @@
#include "nvidia-installer.h"
#include "command-list.h"
+#include "user-interface.h"
+
+/*
+ * Enumeration to identify whether the execution of a distro hook script has
+ * succeeded, failed or the script has not actually been executed
+ */
+
+typedef enum {
+ HOOK_SCRIPT_FAIL = 0,
+ HOOK_SCRIPT_SUCCESS,
+ HOOK_SCRIPT_NO_RUN,
+} HookScriptStatus;
+
typedef enum {
ELF_INVALID_FILE,
@@ -52,6 +65,7 @@ int find_module_utils(Options *op);
int check_selinux(Options *op);
int check_proc_modprobe_path(Options *op);
int check_development_tools(Options *op, Package *p);
+int check_precompiled_kernel_interface_tools(Options *op);
char *extract_version_string(const char *str);
int continue_after_error(Options *op, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
int do_install(Options *op, Package *p, CommandList *c);
@@ -60,6 +74,8 @@ void should_install_compat32_files(Options *op, Package *p);
void should_install_vdpau_wrapper(Options *op, Package *p);
void should_install_uvm(Options *op, Package *p);
void check_installed_files_from_package(Options *op, Package *p);
+int check_installed_file(Options*, const char*, const mode_t, const uint32,
+ ui_message_func *logwarn);
int tls_test(Options *op, int compat_32_libs);
int check_runtime_configuration(Options *op, Package *p);
void collapse_multiple_slashes(char *s);
@@ -69,13 +85,12 @@ int check_for_running_x(Options *op);
int check_for_modular_xorg(Options *op);
int check_for_nvidia_graphics_devices(Options *op, Package *p);
int run_nvidia_xconfig(Options *op, int restore);
-int run_distro_hook(Options *op, const char *hook);
+HookScriptStatus run_distro_hook(Options *op, const char *hook);
int check_for_alternate_install(Options *op);
int check_for_nouveau(Options *op);
int dkms_module_installed(Options *op, const char *version);
int dkms_install_module(Options *op, const char *version, const char *kernel);
int dkms_remove_module(Options *op, const char *version);
-int unprelink(Options *op, const char *filename);
int verify_crc(Options *op, const char *filename, unsigned int crc,
unsigned int *actual_crc);
int secure_boot_enabled(void);
diff --git a/ncurses-ui.c b/ncurses-ui.c
index b0d6e04..10ce732 100644
--- a/ncurses-ui.c
+++ b/ncurses-ui.c
@@ -161,6 +161,8 @@ static void nv_ncurses_command_output (Options*, const char*);
static int nv_ncurses_approve_command_list(Options*, CommandList*,
const char*);
static int nv_ncurses_yes_no (Options*, const int, const char*);
+static int nv_ncurses_multiple_choice (Options *, const char*,
+ const char **, int, int);
static void nv_ncurses_status_begin (Options*, const char*,
const char*);
static void nv_ncurses_status_update (Options*, const float,
@@ -189,6 +191,9 @@ static void nv_ncurses_destroy_region(RegionStruct *);
static void nv_ncurses_draw_button(DataStruct *, RegionStruct *, int, int,
int, int, const char *, bool, bool);
static void nv_ncurses_erase_button(RegionStruct *, int, int, int, int);
+static void draw_buttons(DataStruct *d, const char **buttons, int num_buttons,
+ int button, int button_w, const int *buttons_x,
+ int button_y);
/* helper functions for drawing regions and stuff */
@@ -247,6 +252,7 @@ InstallerUI ui_dispatch_table = {
nv_ncurses_command_output,
nv_ncurses_approve_command_list,
nv_ncurses_yes_no,
+ nv_ncurses_multiple_choice,
nv_ncurses_paged_prompt,
nv_ncurses_status_begin,
nv_ncurses_status_update,
@@ -802,112 +808,27 @@ static int nv_ncurses_approve_command_list(Options *op, CommandList *cl,
static int nv_ncurses_yes_no(Options *op, const int def, const char *msg)
{
- DataStruct *d = (DataStruct *) op->ui_priv;
- int yes_x, no_x, x, y, w, h, yes, ch;
- char *str;
-
- if (!msg) return FALSE;
-
- /* check if the window was resized */
-
- nv_ncurses_check_resize(d, FALSE);
- yes = def;
-
- draw_yes_no:
-
- if (d->message) {
-
- /*
- * XXX we may already have a message region allocated when we
- * enter nv_ncurses_yes_no(): we may have been in the middle
- * of displaying a progress bar when we encountered an error
- * that we need to report. To deal with this situation, throw
- * out the existing message region; nv_ncurses_status_update()
- * and nv_ncurses_status_end() will have to recreate their
- * message region.
- */
-
- nv_ncurses_destroy_region(d->message);
- d->message = NULL;
- }
-
- /* create the message region and print the message in it */
-
- nv_ncurses_do_message_region(d, NULL, msg, FALSE, 2);
-
- /* draw the yes/no buttons */
-
- w = 7;
- h = 1;
- y = d->message->h - 2;
- yes_x = (d->message->w - w*3)/2 + 0;
- no_x = (d->message->w - w*3)/2 + 2*w;
-
- nv_ncurses_draw_button(d, d->message, yes_x, y, w, h, "Yes", yes,FALSE);
- nv_ncurses_draw_button(d, d->message, no_x, y, w, h, "No", !yes, FALSE);
-
- refresh();
-
- /* process key strokes */
-
- do {
- if (nv_ncurses_check_resize(d, FALSE)) goto draw_yes_no;
- ch = getch();
-
- switch (ch) {
- case NV_NCURSES_TAB:
- case KEY_LEFT:
- case KEY_RIGHT:
-
- /*
- * any of left, right, and tab will toggle which button is
- * selected
- */
-
- yes ^= 1;
-
- nv_ncurses_draw_button(d, d->message, yes_x, y, w, h,
- "Yes", yes, FALSE);
- nv_ncurses_draw_button(d, d->message, no_x, y, w, h,
- "No", !yes, FALSE);
- refresh();
- break;
+ const char *buttons[2] = { "Yes", "No" };
- case NV_NCURSES_CTRL('L'):
- nv_ncurses_check_resize(d, TRUE);
- goto draw_yes_no;
- break;
+ return (nv_ncurses_multiple_choice(op, msg, buttons, 2,
+ (def) ? 0 : 1) == 0);
+} /* nv_ncurses_yes_no() */
- default:
- break;
- }
- } while (ch != NV_NCURSES_ENTER);
-
- /* animate the button being pushed down */
-
- x = yes ? yes_x : no_x;
- str = yes ? "Yes" : "No";
-
- nv_ncurses_erase_button(d->message, x, y, w, h);
- nv_ncurses_draw_button(d, d->message, x, y, w, 1, str, TRUE, TRUE);
- refresh();
- usleep(NV_NCURSES_BUTTON_PRESS_TIME);
-
- nv_ncurses_erase_button(d->message, x, y, w, h);
- nv_ncurses_draw_button(d, d->message, x, y, w, h, str, TRUE, FALSE);
- refresh();
- usleep(NV_NCURSES_BUTTON_PRESS_TIME);
-
- /* free the message region */
- nv_ncurses_destroy_region(d->message);
- d->message = NULL;
-
- refresh();
+/*
+ * nv_ncurses_multiple_choice() - display a question with multiple-choice
+ * buttons allowing the user to select a button corresponding to the desired
+ * response. Returns the index of the button selected from the passed-in
+ * buttons array.
+ */
- return yes;
-
-} /* nv_ncurses_yes_no() */
+static int nv_ncurses_multiple_choice(Options *op, const char *question,
+ const char **buttons, int num_buttons,
+ int default_button)
+{
+ return nv_ncurses_paged_prompt(op, question, NULL, NULL, buttons,
+ num_buttons, default_button);
+} /* nv_ncurses_multiple_choice() */
@@ -1714,6 +1635,17 @@ static int nv_ncurses_paged_prompt(Options *op, const char *question,
/* free any existing message region, pager, and pager textrows */
if (d->message) {
+
+ /*
+ * XXX we may already have a message region allocated when we
+ * enter nv_ncurses_paged_prompt(): we may have been in the middle
+ * of displaying a progress bar when we encountered an error
+ * that we need to report. To deal with this situation, throw
+ * out the existing message region; nv_ncurses_status_update()
+ * and nv_ncurses_status_end() will have to recreate their
+ * message region.
+ */
+
nv_ncurses_destroy_region(d->message);
d->message = NULL;
}
@@ -1729,7 +1661,8 @@ static int nv_ncurses_paged_prompt(Options *op, const char *question,
/* create the message region and print the question in it */
- nv_ncurses_do_message_region(d, NULL, question, TRUE, 2);
+ nv_ncurses_do_message_region(d, NULL, question,
+ (pager_title && pager_text), 2);
button_y = d->message->h - 2;
@@ -1743,10 +1676,13 @@ static int nv_ncurses_paged_prompt(Options *op, const char *question,
/* draw the paged text */
- t_pager = d->format_text_rows(NULL, pager_text, d->message->w, TRUE);
- p = nv_ncurses_create_pager(d, 1, d->message->h + 2, d->message->w,
- d->height - d->message->h - 4, t_pager,
- pager_title, cur);
+ if (pager_title && pager_text) {
+ t_pager = d->format_text_rows(NULL, pager_text, d->message->w, TRUE);
+ p = nv_ncurses_create_pager(d, 1, d->message->h + 2, d->message->w,
+ d->height - d->message->h - 4, t_pager,
+ pager_title, cur);
+ }
+
refresh();
/* process key strokes */
@@ -1754,7 +1690,9 @@ static int nv_ncurses_paged_prompt(Options *op, const char *question,
do {
/* if a resize occurred, jump back to the top and redraw */
if (nv_ncurses_check_resize(d, FALSE)) {
- cur = p->cur;
+ if (p) {
+ cur = p->cur;
+ }
goto print_message;
}
@@ -1778,7 +1716,9 @@ static int nv_ncurses_paged_prompt(Options *op, const char *question,
case NV_NCURSES_CTRL('L'):
nv_ncurses_check_resize(d, TRUE);
- cur = p->cur;
+ if (p) {
+ cur = p->cur;
+ }
goto print_message;
break;
@@ -1786,7 +1726,9 @@ static int nv_ncurses_paged_prompt(Options *op, const char *question,
break;
}
- nv_ncurses_pager_handle_events(d, p, ch);
+ if (p) {
+ nv_ncurses_pager_handle_events(d, p, ch);
+ }
} while (ch != NV_NCURSES_ENTER);
/* animate the button being pushed down */
@@ -1812,8 +1754,12 @@ static int nv_ncurses_paged_prompt(Options *op, const char *question,
/* clean up */
- nv_ncurses_free_text_rows(t_pager);
- nv_ncurses_destroy_pager(p);
+ if (t_pager) {
+ nv_ncurses_free_text_rows(t_pager);
+ }
+ if (p) {
+ nv_ncurses_destroy_pager(p);
+ }
nv_ncurses_destroy_region(d->message);
d->message = NULL;
diff --git a/nvidia-installer-ui.h b/nvidia-installer-ui.h
index e8f0c81..8594cb0 100644
--- a/nvidia-installer-ui.h
+++ b/nvidia-installer-ui.h
@@ -127,6 +127,19 @@ typedef struct __nv_installer_ui {
int (*yes_no)(Options *op, const int def, const char *msg);
+
+ /*
+ * multiple_choice - ask the question 'question' with 'num_answers' possible
+ * multiple choice answers in 'answers', with 'default_answer' as the
+ * default answer. Returns the index into 'answers' of the user-selected
+ * answer to 'question'. The names of answers must not begin with digits,
+ * and the caller is responsible for enforcing this.
+ */
+
+ int (*multiple_choice)(Options *op, const char *question,
+ const char **answers, int num_answers,
+ int default_answer);
+
/*
* paged_prompt - ask the question 'question' with 'num_answers' possible
* multiple choice answers in 'answers', with 'default_answer' as the
diff --git a/nvidia-installer.c b/nvidia-installer.c
index 43f5746..60f76b9 100644
--- a/nvidia-installer.c
+++ b/nvidia-installer.c
@@ -46,6 +46,7 @@
#include "update.h"
#include "sanity.h"
#include "option_table.h"
+#include "msg.h"
static void print_version(void);
static void print_help(const char* name, int is_uninstall, int advanced);
@@ -60,16 +61,16 @@ extern const char *pNV_ID;
static void print_version(void)
{
- fmtout("");
- fmtout("%s", pNV_ID);
- fmtoutp(TAB, "The NVIDIA Software Installer for Unix/Linux.");
- fmtout("");
- fmtoutp(TAB, "This program is used to install, upgrade and uninstall "
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "%s", pNV_ID);
+ nv_info_msg(TAB, "The NVIDIA Software Installer for Unix/Linux.");
+ nv_info_msg(NULL, "");
+ nv_info_msg(TAB, "This program is used to install, upgrade and uninstall "
"The NVIDIA Accelerated Graphics Driver Set for %s-%s.",
INSTALLER_OS, INSTALLER_ARCH);
- fmtout("");
- fmtoutp(TAB, "Copyright (C) 2003 - 2010 NVIDIA Corporation.");
- fmtout("");
+ nv_info_msg(NULL, "");
+ nv_info_msg(TAB, "Copyright (C) 2003 - 2010 NVIDIA Corporation.");
+ nv_info_msg(NULL, "");
}
@@ -79,9 +80,9 @@ static void print_version(void)
static void print_help_helper(const char *name, const char *description)
{
- fmtoutp(TAB, "%s", name);
- fmtoutp(BIGTAB, "%s", description);
- fmtout("");
+ nv_info_msg(TAB, "%s", name);
+ nv_info_msg(BIGTAB, "%s", description);
+ nv_info_msg(NULL, "");
}
static void print_options(int is_uninstall, int advanced)
@@ -105,9 +106,9 @@ static void print_help(const char* name, int is_uninstall, int advanced)
{
print_version();
- fmtout("");
- fmtout("%s [options]", name);
- fmtout("");
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "%s [options]", name);
+ nv_info_msg(NULL, "");
print_options(is_uninstall, advanced);
}
@@ -297,7 +298,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
else if (strcasecmp(strval, "classic") == 0)
op->which_tls = FORCE_CLASSIC_TLS;
else {
- fmterr("Invalid parameter for '--force-tls'");
+ nv_error_msg("Invalid parameter for '--force-tls'");
goto fail;
}
break;
@@ -308,7 +309,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
else if (strcasecmp(strval, "classic") == 0)
op->which_tls_compat32 = FORCE_CLASSIC_TLS;
else {
- fmterr("Invalid parameter for '--force-tls-compat32'");
+ nv_error_msg("Invalid parameter for '--force-tls-compat32'");
goto fail;
}
break;
@@ -353,7 +354,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
else if (strcasecmp(strval, "no") == 0)
op->selinux_option = SELINUX_FORCE_NO;
else if (strcasecmp(strval, "default")) {
- fmterr("Invalid parameter for '--force-selinux'");
+ nv_error_msg("Invalid parameter for '--force-selinux'");
goto fail;
}
break;
@@ -415,7 +416,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
break;
case MULTIPLE_KERNEL_MODULES_OPTION:
if (intval < 0) {
- fmterr("Invalid parameter for '--multiple-kernel-modules'");
+ nv_error_msg("Invalid parameter for '--multiple-kernel-modules'");
goto fail;
}
op->multiple_kernel_modules = TRUE;
@@ -431,7 +432,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
break;
case NO_UVM_OPTION:
op->install_uvm = FALSE;
- break;
+ break;
case NO_CHECK_FOR_ALTERNATE_INSTALLS_OPTION:
op->check_for_alternate_installs = FALSE;
break;
@@ -465,7 +466,7 @@ static void parse_commandline(int argc, char *argv[], Options *op)
/*
* We are printing help text for use by makeself.sh; we do not
* want this formatted to the width of the current terminal,
- * so hardcode the width used by fmtout() to 65.
+ * so hardcode the width used by nv_info_msg() to 65.
*/
reset_current_terminal_width(65);
@@ -499,8 +500,8 @@ static void parse_commandline(int argc, char *argv[], Options *op)
return;
fail:
- fmterr("Invalid commandline, please run `%s --help` "
- "for usage information.", argv[0]);
+ nv_error_msg("Invalid commandline, please run `%s --help` "
+ "for usage information.", argv[0]);
nvfree((void*)op);
exit(1);
} /* parse_commandline() */
diff --git a/nvidia-installer.h b/nvidia-installer.h
index 904d43c..189a17b 100644
--- a/nvidia-installer.h
+++ b/nvidia-installer.h
@@ -35,10 +35,9 @@
*/
typedef enum {
- LDCONFIG = 0,
+ MIN_SYSTEM_UTILS = 0,
+ LDCONFIG = MIN_SYSTEM_UTILS,
LDD,
- LD,
- OBJCOPY,
GREP,
DMESG,
TAIL,
@@ -49,7 +48,9 @@ typedef enum {
} SystemUtils;
typedef enum {
- CHCON = MAX_SYSTEM_UTILS,
+ MIN_SYSTEM_OPTIONAL_UTILS = MAX_SYSTEM_UTILS,
+ OBJCOPY = MIN_SYSTEM_OPTIONAL_UTILS,
+ CHCON,
SELINUX_ENABLED,
GETENFORCE,
EXECSTACK,
@@ -66,15 +67,32 @@ typedef enum {
*/
typedef enum {
- INSMOD = MAX_SYSTEM_OPTIONAL_UTILS,
+ MIN_MODULE_UTILS = MAX_SYSTEM_OPTIONAL_UTILS,
+ INSMOD = MIN_MODULE_UTILS,
MODPROBE,
RMMOD,
LSMOD,
DEPMOD,
- MAX_UTILS
+ MAX_MODULE_UTILS
} ModuleUtils;
/*
+ * Enumerated type, listing each of the develop utilities we'll need.
+ * Keep this enum in sync with the develop_utils string array in
+ * misc.c:check_development_tools().
+ */
+
+typedef enum {
+ MIN_DEVELOP_UTILS = MAX_MODULE_UTILS,
+ CC = MIN_DEVELOP_UTILS,
+ MAKE,
+ LD,
+ MAX_DEVELOP_UTILS
+} DevelopUtils;
+
+#define MAX_UTILS MAX_DEVELOP_UTILS
+
+/*
* Enumerated type of distributions; this isn't an exhaustive list of
* supported distributions... just distributions that have asked for
* special behavior.
@@ -443,9 +461,9 @@ typedef struct __package {
#define XORG7_DEFAULT_X_MODULEDIR "xorg/modules"
/*
- * Debian GNU/Linux for x86-64 installs 32-bit compatibility
- * libraries relative to a chroot-like top-level directory; the
- * prefix below is prepended to the full paths.
+ * Older versions of Debian GNU/Linux for x86-64 install 32-bit
+ * compatibility libraries relative to a chroot-like top-level
+ * directory; the prefix below is prepended to the full paths.
*/
#define DEBIAN_DEFAULT_COMPAT32_CHROOT "/emul/ia32-linux"
@@ -464,6 +482,13 @@ typedef struct __package {
*/
#define UBUNTU_DEFAULT_COMPAT32_LIBDIR "lib32"
+/*
+ * Newer versions of Debian GNU/Linux may install 32-bit
+ * compatibility libraries to ../lib/i386-linux-gnu instead
+ * of ../lib32.
+ */
+
+#define DEBIAN_DEFAULT_COMPAT32_LIBDIR "lib/i386-linux-gnu"
#define DEFAULT_PROC_MOUNT_POINT "/proc"
diff --git a/stream-ui.c b/stream-ui.c
index 0b33199..04b5eab 100644
--- a/stream-ui.c
+++ b/stream-ui.c
@@ -33,6 +33,7 @@
#include "misc.h"
#include "files.h"
#include "common-utils.h"
+#include "msg.h"
/* prototypes of each of the stream ui functions */
@@ -45,6 +46,8 @@ void stream_message (Options*, int level, const char*);
void stream_command_output (Options*, const char*);
int stream_approve_command_list(Options*, CommandList*, const char*);
int stream_yes_no (Options*, const int, const char*);
+int stream_multiple_choice (Options *op, const char *, const char **,
+ int, int);
int stream_paged_prompt (Options *op, const char *, const char *,
const char *, const char **, int, int);
void stream_status_begin (Options*, const char*, const char*);
@@ -62,6 +65,7 @@ InstallerUI stream_ui_dispatch_table = {
stream_command_output,
stream_approve_command_list,
stream_yes_no,
+ stream_multiple_choice,
stream_paged_prompt,
stream_status_begin,
stream_status_update,
@@ -148,9 +152,10 @@ int stream_init(Options *op, FormatTextRows format_text_rows)
if (!op->silent) {
- fmtout("");
- fmtout("Welcome to the NVIDIA Software Installer for Unix/Linux");
- fmtout("");
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "Welcome to the NVIDIA Software Installer for "
+ "Unix/Linux");
+ nv_info_msg(NULL, "");
/* register the SIGWINCH signal handler */
@@ -185,8 +190,8 @@ char *stream_get_input(Options *op, const char *def, const char *msg)
{
char *buf;
- fmt(stdout, NULL, "");
- fmt(stdout, NULL, "%s", msg);
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "%s", msg);
fprintf(stdout, " [default: '%s']: ", def);
fflush(stdout);
@@ -214,17 +219,18 @@ int stream_display_license(Options *op, const char *license)
{
char *str;
- fmtout("");
- fmtout("Please read the following LICENSE and type \""
- "accept\" followed by the Enter key to accept the license, or "
- "type anything else to not accept and exit nvidia-installer.");
- fmtout("");
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "Please read the following LICENSE and type \""
+ "accept\" followed by the Enter key to accept the "
+ "license, or type anything else to not accept and "
+ "exit nvidia-installer.");
+ nv_info_msg(NULL, "");
- fmtout("________");
- fmtout("");
+ nv_info_msg(NULL, "________");
+ nv_info_msg(NULL, "");
printf("%s", license);
- fmtout("________");
- fmtout("");
+ nv_info_msg(NULL, "________");
+ nv_info_msg(NULL, "");
printf("Accept? (Type \"Accept\" to accept, or anything else to abort): ");
fflush(stdout);
@@ -274,9 +280,15 @@ void stream_message(Options *op, const int level, const char *msg)
if ((level == NV_MSG_LEVEL_LOG) && (d->status_active)) return;
- if (msg_attrs[level].newline) fmt(msg_attrs[level].stream, NULL, "");
- fmt(msg_attrs[level].stream, msg_attrs[level].prefix, "%s", msg);
- if (msg_attrs[level].newline) fmt(msg_attrs[level].stream, NULL, "");
+ if (msg_attrs[level].newline) {
+ nv_info_msg_to_file(msg_attrs[level].stream, NULL, "");
+ }
+ nv_info_msg_to_file(msg_attrs[level].stream,
+ msg_attrs[level].prefix,
+ "%s", msg);
+ if (msg_attrs[level].newline) {
+ nv_info_msg_to_file(msg_attrs[level].stream, NULL, "");
+ }
} /* stream_message() */
@@ -295,7 +307,7 @@ void stream_command_output(Options *op, const char *msg)
if ((!op->expert) || (d->status_active)) return;
- fmtoutp(" ", "%s", msg);
+ nv_info_msg(" ", "%s", msg);
} /* stream_command_output() */
@@ -314,10 +326,10 @@ int stream_approve_command_list(Options *op, CommandList *cl,
char *perms;
const char *prefix = " --> ";
- fmtout("");
- fmtout("The following operations will be performed to install the %s:",
- descr);
- fmtout("");
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "The following operations will be performed to install the %s:",
+ descr);
+ nv_info_msg(NULL, "");
for (i = 0; i < cl->num; i++) {
c = &cl->cmds[i];
@@ -326,37 +338,37 @@ int stream_approve_command_list(Options *op, CommandList *cl,
case INSTALL_CMD:
perms = mode_to_permission_string(c->mode);
- fmtoutp(prefix, "install the file '%s' as '%s' with "
- "permissions '%s'", c->s0, c->s1, perms);
+ nv_info_msg(prefix, "install the file '%s' as '%s' with "
+ "permissions '%s'", c->s0, c->s1, perms);
free(perms);
if (c->s2) {
- fmtoutp(prefix, "execute the command `%s`", c->s2);
+ nv_info_msg(prefix, "execute the command `%s`", c->s2);
}
break;
case RUN_CMD:
- fmtoutp(prefix, "execute the command `%s`", c->s0);
+ nv_info_msg(prefix, "execute the command `%s`", c->s0);
break;
case SYMLINK_CMD:
- fmtoutp(prefix, "create a symbolic link '%s' to '%s'",
- c->s0, c->s1);
+ nv_info_msg(prefix, "create a symbolic link '%s' to '%s'",
+ c->s0, c->s1);
break;
case BACKUP_CMD:
- fmtoutp(prefix, "back up the file '%s'", c->s0);
+ nv_info_msg(prefix, "back up the file '%s'", c->s0);
break;
case DELETE_CMD:
- fmtoutp(prefix, "delete file '%s'", c->s0);
+ nv_info_msg(prefix, "delete file '%s'", c->s0);
break;
default:
- fmterr("Error in CommandList! (cmd: %d; s0: '%s';"
- "s1: '%s'; s2: '%s'; mode: %04o)",
- c->cmd, c->s0, c->s1, c->s2, c->mode);
- fmterr("Aborting installation.");
+ nv_error_msg("Error in CommandList! (cmd: %d; s0: '%s';"
+ "s1: '%s'; s2: '%s'; mode: %04o)",
+ c->cmd, c->s0, c->s1, c->s2, c->mode);
+ nv_error_msg("Aborting installation.");
return FALSE;
break;
}
@@ -366,7 +378,7 @@ int stream_approve_command_list(Options *op, CommandList *cl,
if (!stream_yes_no(op, TRUE, "\nIs this acceptable? (answering 'no' will "
"abort installation)")) {
- fmterr("Command list not accepted; exiting installation.");
+ nv_error_msg("Command list not accepted; exiting installation.");
return FALSE;
}
@@ -386,8 +398,8 @@ int stream_yes_no(Options *op, const int def, const char *msg)
char *buf;
int eof, ret = def;
- fmt(stdout, NULL, "");
- fmt(stdout, NULL, "%s", msg);
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "%s", msg);
if (def) fprintf(stdout, " [default: (Y)es]: ");
else fprintf(stdout, " [default: (N)o]: ");
fflush(stdout);
@@ -448,46 +460,35 @@ static int select_option(const char **options, int num_options,
/*
- * stream_paged_prompt() - display a question with multiple-choice answers
- * along with a text area (not scrollable), allowing the user to review the text
- * and select a button corresponding to the desired response. Returns the index
- * answer selected from the passed-in answers array.
+ * stream_multiple_choice() - display a question with multiple-choice answers
+ * allowing the user to select a button corresponding to the desired response.
+ * Returns the index answer selected from the passed-in answers array.
*/
-int stream_paged_prompt(Options *op, const char *question,
- const char *pager_title, const char *pager_text,
- const char **answers, int num_answers,
- int default_answer)
+int stream_multiple_choice(Options *op, const char *question,
+ const char **answers, int num_answers,
+ int default_answer)
{
int ret = default_answer;
- fmtout("");
- fmtout("________");
- fmtout("");
- fmtout("%s", pager_title);
- fmtout("");
- fmtout("%s", pager_text);
- fmtout("");
- fmtout("________");
-
do {
char *str;
int i;
if (ret < 0) {
- fmterr("Invalid response!");
+ nv_error_msg("Invalid response!");
}
- fmtout("");
- fmtout("%s", question);
- fmtout("Valid responses are: ");
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "%s", question);
+ nv_info_msg(NULL, "Valid responses are: ");
for (i = 0; i < num_answers; i++) {
- fmtout(" (%d)\t\"%s\"%s", i + 1, answers[i],
- i == default_answer ? " [ default ]" : "");
+ nv_info_msg(NULL, " (%d)\t\"%s\"%s", i + 1, answers[i],
+ i == default_answer ? " [ default ]" : "");
}
- fmtout("Please select your response by number or name:");
+ nv_info_msg(NULL, "Please select your response by number or name:");
str = fget_next_line(stdin, NULL);
ret = select_option(answers, num_answers, default_answer, str);
@@ -500,6 +501,33 @@ int stream_paged_prompt(Options *op, const char *question,
/*
+ * stream_paged_prompt() - display a question with multiple-choice answers
+ * along with a text area (not scrollable), allowing the user to review the text
+ * and select a button corresponding to the desired response. Returns the index
+ * answer selected from the passed-in answers array.
+ */
+
+int stream_paged_prompt(Options *op, const char *question,
+ const char *pager_title, const char *pager_text,
+ const char **answers, int num_answers,
+ int default_answer)
+{
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "________");
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "%s", pager_title);
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "%s", pager_text);
+ nv_info_msg(NULL, "");
+ nv_info_msg(NULL, "________");
+
+ return stream_multiple_choice(op, question, answers, num_answers,
+ default_answer);
+}
+
+
+
+/*
* stream_status_begin() - we assume that title is always passed, but
* sometimes msg will be NULL.
*/
@@ -510,7 +538,7 @@ void stream_status_begin(Options *op, const char *title, const char *msg)
d->status_active = TRUE;
- fmtout("%s", title);
+ nv_info_msg(NULL, "%s", title);
d->status_label = nvstrdup(msg);
print_status_bar(d, STATUS_BEGIN, 0.0);
diff --git a/user-interface.c b/user-interface.c
index 6b655a0..e30df5f 100644
--- a/user-interface.c
+++ b/user-interface.c
@@ -394,6 +394,36 @@ int ui_yes_no (Options *op, const int def, const char *fmt, ...)
} /* ui_yes_no() */
+int ui_multiple_choice (Options *op, const char **answers, int num_answers,
+ int default_answer, const char *fmt, ...)
+{
+ char *question, *tmp = NULL;
+ int ret;
+
+ NV_VSNPRINTF(question, fmt);
+
+ if (op->no_questions) {
+ ret = default_answer;
+ } else {
+ ret = __ui->multiple_choice(op, question, answers, num_answers,
+ default_answer);
+ }
+
+ tmp = nvstrcat("(Answer: ", answers[ret], ")", NULL);
+
+ if (!op->silent) {
+ __ui->message(op, NV_MSG_LEVEL_LOG, tmp);
+ }
+
+ log_printf(op, NV_BULLET_STR, "%s", tmp);
+ nvfree(question);
+ nvfree(tmp);
+
+ return ret;
+
+} /* ui_multiple_choice() */
+
+
int ui_paged_prompt (Options *op, const char *question, const char *pager_title,
const char *pager_text, const char **answers,
int num_answers, int default_answer)
diff --git a/user-interface.h b/user-interface.h
index ac216c3..eeee533 100644
--- a/user-interface.h
+++ b/user-interface.h
@@ -38,6 +38,8 @@ void ui_expert (Options*, const char*, ...) NV_ATTRIB
void ui_command_output (Options*, const char*, ...) NV_ATTRIBUTE_PRINTF(2, 3);
int ui_approve_command_list(Options*, CommandList*,const char*, ...) NV_ATTRIBUTE_PRINTF(3, 4);
int ui_yes_no (Options*, const int, const char*, ...) NV_ATTRIBUTE_PRINTF(3, 4);
+int ui_multiple_choice (Options *, const char **, int, int,
+ const char *, ...) NV_ATTRIBUTE_PRINTF(5, 6);
int ui_paged_prompt (Options *, const char *, const char *,
const char *, const char **, int, int);
void ui_status_begin (Options*, const char*, const char*, ...) NV_ATTRIBUTE_PRINTF(3, 4);
@@ -45,4 +47,7 @@ void ui_status_update (Options*, const float, const char*, ...) NV_ATTRIB
void ui_status_end (Options*, const char*, ...) NV_ATTRIBUTE_PRINTF(2, 3);
void ui_close (Options*);
+/* Useful when different message types may be suitable in different contexts */
+typedef void ui_message_func (Options*, const char*, ...) NV_ATTRIBUTE_PRINTF(2, 3);
+
#endif /* __NVIDIA_INSTALLER_USER_INTERFACE_H__ */
diff --git a/utils.mk b/utils.mk
index ce645c7..a725f14 100644
--- a/utils.mk
+++ b/utils.mk
@@ -114,6 +114,7 @@ endif
TARGET_ARCH_ABI ?=
OUTPUTDIR ?= _out/$(TARGET_OS)_$(TARGET_ARCH)
+OUTPUTDIR_ABSOLUTE ?= $(CURDIR)/$(OUTPUTDIR)
NV_QUIET_COMMAND_REMOVED_TARGET_PREFIX ?=
diff --git a/version.mk b/version.mk
index 2bca142..591ef07 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 331.38
+NVIDIA_VERSION = 334.16