This commit is contained in:
Aaron Plattner
2014-02-09 11:41:07 -08:00
parent e49143d67b
commit 63b65ddce0
25 changed files with 1343 additions and 988 deletions

View File

@@ -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) \

View File

@@ -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;
}
/* check if the file still matches its backup log entry */
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);
}
}
}
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;
}

View File

@@ -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 }
};

View File

@@ -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.

View File

@@ -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

View File

@@ -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;
}
}

416
common-utils/msg.c Normal file
View File

@@ -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() */

137
common-utils/msg.h Normal file
View File

@@ -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__ */

View File

@@ -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,

69
files.c
View File

@@ -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

View File

@@ -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;
if (!entry.name) entry.name = entry.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 (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;

147
kernel.c
View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

330
misc.c
View File

@@ -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);
@@ -819,6 +818,23 @@ int check_development_tools(Options *op, Package *p)
} /* check_development_tools() */
/*
* 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
@@ -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);

19
misc.h
View File

@@ -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);

View File

@@ -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,114 +808,29 @@ 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;
const char *buttons[2] = { "Yes", "No" };
/* 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;
case NV_NCURSES_CTRL('L'):
nv_ncurses_check_resize(d, TRUE);
goto draw_yes_no;
break;
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();
return yes;
return (nv_ncurses_multiple_choice(op, msg, buttons, 2,
(def) ? 0 : 1) == 0);
} /* nv_ncurses_yes_no() */
/*
* 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.
*/
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;

View File

@@ -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

View File

@@ -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() */

View File

@@ -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,14 +67,31 @@ 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
@@ -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"

View File

@@ -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);
@@ -447,6 +459,47 @@ static int select_option(const char **options, int num_options,
/*
* 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_multiple_choice(Options *op, const char *question,
const char **answers, int num_answers,
int default_answer)
{
int ret = default_answer;
do {
char *str;
int i;
if (ret < 0) {
nv_error_msg("Invalid response!");
}
nv_info_msg(NULL, "");
nv_info_msg(NULL, "%s", question);
nv_info_msg(NULL, "Valid responses are: ");
for (i = 0; i < num_answers; i++) {
nv_info_msg(NULL, " (%d)\t\"%s\"%s", i + 1, answers[i],
i == default_answer ? " [ default ]" : "");
}
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);
free(str);
} while (ret < 0);
return ret;
}
/*
* stream_paged_prompt() - display a question with multiple-choice answers
* along with a text area (not scrollable), allowing the user to review the text
@@ -459,42 +512,17 @@ int stream_paged_prompt(Options *op, const char *question,
const char **answers, int num_answers,
int default_answer)
{
int ret = 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, "________");
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!");
}
fmtout("");
fmtout("%s", question);
fmtout("Valid responses are: ");
for (i = 0; i < num_answers; i++) {
fmtout(" (%d)\t\"%s\"%s", i + 1, answers[i],
i == default_answer ? " [ default ]" : "");
}
fmtout("Please select your response by number or name:");
str = fget_next_line(stdin, NULL);
ret = select_option(answers, num_answers, default_answer, str);
free(str);
} while (ret < 0);
return ret;
return stream_multiple_choice(op, question, answers, num_answers,
default_answer);
}
@@ -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);

View File

@@ -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)

View File

@@ -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__ */

View File

@@ -114,6 +114,7 @@ endif
TARGET_ARCH_ABI ?=
OUTPUTDIR ?= _out/$(TARGET_OS)_$(TARGET_ARCH)
OUTPUTDIR_ABSOLUTE ?= $(CURDIR)/$(OUTPUTDIR)
NV_QUIET_COMMAND_REMOVED_TARGET_PREFIX ?=

View File

@@ -1 +1 @@
NVIDIA_VERSION = 331.38
NVIDIA_VERSION = 334.16