mirror of
https://github.com/NVIDIA/nvidia-installer.git
synced 2025-07-23 02:13:00 +02:00
334.16
This commit is contained in:
5
Makefile
5
Makefile
@@ -96,7 +96,7 @@ GEN_UI_ARRAY = $(OUTPUTDIR)/gen-ui-array
|
||||
CONFIG_H = $(OUTPUTDIR)/config.h
|
||||
|
||||
MANPAGE = $(OUTPUTDIR)/nvidia-installer.1.gz
|
||||
GEN_MANPAGE_OPTS = $(OUTPUTDIR)/gen-manpage-opts
|
||||
GEN_MANPAGE_OPTS = $(OUTPUTDIR_ABSOLUTE)/gen-manpage-opts
|
||||
OPTIONS_1_INC = $(OUTPUTDIR)/options.1.inc
|
||||
|
||||
# Setup some architecture specific build options
|
||||
@@ -158,6 +158,7 @@ MKPRECOMPILED_OBJS = $(call BUILD_OBJECT_LIST,$(MKPRECOMPILED_SRC))
|
||||
MAKESELF_HELP_SCRIPT_SRC = makeself-help-script.c
|
||||
MAKESELF_HELP_SCRIPT_SRC += $(COMMON_UTILS_DIR)/common-utils.c
|
||||
MAKESELF_HELP_SCRIPT_SRC += $(COMMON_UTILS_DIR)/nvgetopt.c
|
||||
MAKESELF_HELP_SCRIPT_SRC += $(COMMON_UTILS_DIR)/msg.c
|
||||
|
||||
BUILD_MAKESELF_OBJECT_LIST = \
|
||||
$(patsubst %.o,%.makeself.o,$(call BUILD_OBJECT_LIST,$(1)))
|
||||
@@ -371,7 +372,7 @@ $(GEN_MANPAGE_OPTS): $(GEN_MANPAGE_OPTS_OBJS)
|
||||
$(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_BIN_LDFLAGS) $^ -o $@
|
||||
|
||||
$(OPTIONS_1_INC): $(GEN_MANPAGE_OPTS)
|
||||
@./$< > $@
|
||||
@$< > $@
|
||||
|
||||
$(MANPAGE): nvidia-installer.1.m4 $(OPTIONS_1_INC) $(VERSION_MK)
|
||||
$(call quiet_cmd,M4) \
|
||||
|
65
backup.c
65
backup.c
@@ -541,7 +541,7 @@ int log_mkdir(Options *op, const char *dirs)
|
||||
*/
|
||||
static int reverse_strlen_compare(const void *a, const void *b)
|
||||
{
|
||||
return strlen((const char *)b) - strlen((const char *)a);
|
||||
return strlen(*(char * const *)b) - strlen(*(char * const *)a);
|
||||
}
|
||||
|
||||
|
||||
@@ -586,7 +586,7 @@ static int rmdir_recursive(Options *op)
|
||||
|
||||
qsort(dirs, lines, sizeof(char*), reverse_strlen_compare);
|
||||
|
||||
for (i = lines; i < lines; i++) {
|
||||
for (i = 0; i < lines; i++) {
|
||||
if (dirs[i]) {
|
||||
/* Ignore empty lines and the backup directory itself, since it is
|
||||
* never empty as long as the dirs file is still around. */
|
||||
@@ -1094,46 +1094,13 @@ static int check_backup_log_entries(Options *op, BackupInfo *b)
|
||||
switch (e->num) {
|
||||
|
||||
case INSTALLED_FILE:
|
||||
|
||||
/* check if the file is still there */
|
||||
|
||||
if (access(e->filename, F_OK) == -1) {
|
||||
ui_log(op, "Unable to access previously installed file "
|
||||
"'%s' (%s).", e->filename, strerror(errno));
|
||||
ret = e->ok = FALSE;
|
||||
} else {
|
||||
/* check if the file still has the same crc; if not, try
|
||||
* un-prelinking it and check the crc again */
|
||||
if (!verify_crc(op, e->filename, e->crc, &crc)) {
|
||||
ui_expert(op, "The previously installed file '%s' has a "
|
||||
"different checksum (%ul) than when it was "
|
||||
"installed (%ul). This may be due to prelinking; "
|
||||
"attempting `prelink -u %s` to restore the file.",
|
||||
e->filename, crc, e->crc, e->filename);
|
||||
|
||||
if (unprelink(op, e->filename) != 0) {
|
||||
ui_log(op, "The previously installed file '%s' seems "
|
||||
"to have changed, but `prelink -u` failed; "
|
||||
"unable to restore '%s' to an un-prelinked "
|
||||
"state.", e->filename, e->filename);
|
||||
ret = e->ok = FALSE;
|
||||
} else if (!verify_crc(op, e->filename, e->crc, &crc)) {
|
||||
ui_log(op, "The previously installed file '%s' has a "
|
||||
"different checksum (%ul) after running `pre"
|
||||
"link -u` than when it was installed (%ul).",
|
||||
e->filename, crc, e->crc);
|
||||
ret = e->ok = FALSE;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
@@ -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 }
|
||||
};
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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
416
common-utils/msg.c
Normal 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
137
common-utils/msg.h
Normal 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__ */
|
@@ -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
69
files.c
@@ -1196,12 +1196,18 @@ int directory_exists(Options *op, const char *dir)
|
||||
|
||||
int confirm_path(Options *op, const char *path)
|
||||
{
|
||||
const char *choices[2] = {
|
||||
"Create directory",
|
||||
"Abort installation"
|
||||
};
|
||||
|
||||
/* return TRUE if the path already exists and is a directory */
|
||||
|
||||
if (directory_exists(op, path)) return TRUE;
|
||||
|
||||
if (ui_yes_no(op, TRUE, "The directory '%s' does not exist; "
|
||||
"create?", path)) {
|
||||
if (ui_multiple_choice(op, choices, 2, 0, "The directory '%s' does not "
|
||||
"exist; would you like to create it, or would you "
|
||||
"prefer to abort installation?", path) == 0) {
|
||||
if (mkdir_recursive(op, path, 0755)) {
|
||||
return TRUE;
|
||||
} else {
|
||||
@@ -1569,11 +1575,18 @@ int check_for_existing_rpms(Options *op)
|
||||
nvfree(cmd);
|
||||
|
||||
if (ret == 0) {
|
||||
if (!ui_yes_no(op, TRUE, "An %s rpm appears to already be "
|
||||
"installed on your system. As part of installing "
|
||||
"the new driver, this %s rpm will be uninstalled. "
|
||||
"Are you sure you want to continue? ('no' will "
|
||||
"abort installation)", rpms[i], rpms[i])) {
|
||||
|
||||
const char *choices[2] = {
|
||||
"Continue installation",
|
||||
"Abort installation"
|
||||
};
|
||||
|
||||
if (ui_multiple_choice(op, choices, 2, 0, "An %s rpm appears to "
|
||||
"already be installed on your system. As "
|
||||
"part of installing the new driver, this %s "
|
||||
"rpm will be uninstalled. Are you sure you "
|
||||
"want to continue?",
|
||||
rpms[i], rpms[i]) == 1) {
|
||||
ui_log(op, "Installation aborted.");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -2175,23 +2188,43 @@ void get_default_prefixes_and_paths(Options *op)
|
||||
|
||||
if (op->distro == DEBIAN && !op->compat32_chroot) {
|
||||
/*
|
||||
* Newer versions of Debian have moved to the Ubuntu style of compat32
|
||||
* path, so use that if it exists.
|
||||
* Newer versions of Debian install 32-bit compatibility libraries
|
||||
* to dedicated directories that are not part of a chroot structure.
|
||||
* Search for the known paths and use the first one that is found.
|
||||
*/
|
||||
char *default_path = nvstrcat(op->compat32_prefix, "/"
|
||||
UBUNTU_DEFAULT_COMPAT32_LIBDIR, NULL);
|
||||
struct stat buf;
|
||||
if (lstat(default_path, &buf) < 0 || S_ISLNK(buf.st_mode)) {
|
||||
|
||||
char *debian_compat32_paths[] = { DEBIAN_DEFAULT_COMPAT32_LIBDIR,
|
||||
UBUNTU_DEFAULT_COMPAT32_LIBDIR };
|
||||
int i, found = FALSE;
|
||||
|
||||
for (i = 0; i < ARRAY_LEN(debian_compat32_paths); i++) {
|
||||
char *default_path = nvstrcat(op->compat32_prefix, "/",
|
||||
debian_compat32_paths[i], NULL);
|
||||
|
||||
struct stat buf;
|
||||
|
||||
if (lstat(default_path, &buf) == 0 && !S_ISLNK(buf.st_mode)) {
|
||||
/* path exists and is not a symbolic link, so use it */
|
||||
op->compat32_libdir = debian_compat32_paths[i];
|
||||
found = TRUE;
|
||||
}
|
||||
|
||||
nvfree(default_path);
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/*
|
||||
* Path doesn't exist or is a symbolic link. Use the compat32
|
||||
* Paths don't exist or are symbolic links. Use the compat32
|
||||
* chroot path instead.
|
||||
*/
|
||||
|
||||
op->compat32_chroot = DEBIAN_DEFAULT_COMPAT32_CHROOT;
|
||||
} else {
|
||||
/* <prefix>/lib32 exists, so use that */
|
||||
op->compat32_libdir = UBUNTU_DEFAULT_COMPAT32_LIBDIR;
|
||||
}
|
||||
nvfree(default_path);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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
147
kernel.c
@@ -171,7 +171,7 @@ int determine_kernel_module_installation_path(Options *op)
|
||||
|
||||
static int run_conftest(Options *op, Package *p, const char *args, char **result)
|
||||
{
|
||||
char *CC, *cmd, *arch;
|
||||
char *cmd, *arch;
|
||||
int ret;
|
||||
|
||||
if (result)
|
||||
@@ -181,13 +181,10 @@ static int run_conftest(Options *op, Package *p, const char *args, char **result
|
||||
if (!arch)
|
||||
return FALSE;
|
||||
|
||||
CC = getenv("CC");
|
||||
if (!CC) CC = "cc";
|
||||
|
||||
cmd = nvstrcat("sh \"", p->kernel_module_build_directory,
|
||||
"/conftest.sh\" \"", CC, "\" \"", CC, "\" \"", arch, "\" \"",
|
||||
op->kernel_source_path, "\" \"", op->kernel_output_path,
|
||||
"\" ", args, NULL);
|
||||
"/conftest.sh\" \"", op->utils[CC], "\" \"", op->utils[CC],
|
||||
"\" \"", arch, "\" \"", op->kernel_source_path, "\" \"",
|
||||
op->kernel_output_path, "\" ", args, NULL);
|
||||
|
||||
ret = run_command(op, cmd, result, FALSE, 0, TRUE);
|
||||
nvfree(cmd);
|
||||
@@ -432,6 +429,11 @@ static int attach_signature(Options *op, Package *p,
|
||||
char *module_path;
|
||||
int ret = FALSE, command_ret;
|
||||
|
||||
const char *choices[2] = {
|
||||
"Install unsigned kernel module",
|
||||
"Abort installation"
|
||||
};
|
||||
|
||||
ui_log(op, "Attaching module signature to linked kernel module.");
|
||||
|
||||
module_path = nvstrcat(p->kernel_module_build_directory, "/",
|
||||
@@ -456,27 +458,30 @@ static int attach_signature(Options *op, Package *p,
|
||||
attach_done:
|
||||
fclose(module_file);
|
||||
} else {
|
||||
ret = ui_yes_no(op, FALSE,
|
||||
"A detached signature was included with the "
|
||||
"precompiled interface, but opening the linked "
|
||||
"kernel module and/or the signature file failed."
|
||||
"\n\nThe detached signature will not be added; "
|
||||
"would you still like to install the unsigned "
|
||||
"kernel module?");
|
||||
ret = (ui_multiple_choice(op, choices, 2, 1,
|
||||
"A detached signature was included with "
|
||||
"the precompiled interface, but opening "
|
||||
"the linked kernel module and/or the "
|
||||
"signature file failed.\n\nThe detached "
|
||||
"signature will not be added; would you "
|
||||
"still like to install the unsigned "
|
||||
"kernel module?") == 0);
|
||||
}
|
||||
} else {
|
||||
ret = ui_yes_no(op, FALSE,
|
||||
"A detached signature was included with the "
|
||||
"precompiled interface, but the checksum of the linked "
|
||||
"kernel module (%d) did not match the checksum of the "
|
||||
"the kernel module for which the detached signature "
|
||||
"was generated (%d).\n\nThis can happen if the linker "
|
||||
"on the installation target system is not the same as "
|
||||
"the linker on the system that built the precompiled "
|
||||
"interface.\n\nThe detached signature will not be "
|
||||
"added; would you still like to install the unsigned "
|
||||
"kernel module?", actual_crc,
|
||||
fileInfo->linked_module_crc);
|
||||
ret = (ui_multiple_choice(op, choices, 2, 1,
|
||||
"A detached signature was included with the "
|
||||
"precompiled interface, but the checksum of "
|
||||
"the linked kernel module (%d) did not match "
|
||||
"the checksum of the the kernel module for "
|
||||
"which the detached signature was generated "
|
||||
"(%d).\n\nThis can happen if the linker on "
|
||||
"the installation target system is not the "
|
||||
"same as the linker on the system that built "
|
||||
"the precompiled interface.\n\nThe detached "
|
||||
"signature will not be added; would you "
|
||||
"still like to install the unsigned kernel "
|
||||
"module?", actual_crc,
|
||||
fileInfo->linked_module_crc) == 0);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
@@ -584,7 +589,7 @@ static int build_kernel_module_helper(Options *op, const char *dir,
|
||||
ui_status_begin(op, tmp, "Building");
|
||||
nvfree(tmp);
|
||||
|
||||
cmd = nvstrcat("cd ", dir, "; make module",
|
||||
cmd = nvstrcat("cd ", dir, "; ", op->utils[MAKE], " module",
|
||||
" SYSSRC=", op->kernel_source_path,
|
||||
" SYSOUT=", op->kernel_output_path,
|
||||
instances, NULL);
|
||||
@@ -598,11 +603,13 @@ static int build_kernel_module_helper(Options *op, const char *dir,
|
||||
ui_status_end(op, "Error.");
|
||||
ui_error(op, "Unable to build the %s kernel module.", module);
|
||||
/* XXX need more descriptive error message */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ui_status_end(op, "done.");
|
||||
|
||||
return ret == 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -633,7 +640,7 @@ static int check_file(Options *op, const char *dir, const char *filename,
|
||||
int build_kernel_module(Options *op, Package *p)
|
||||
{
|
||||
char *result, *cmd;
|
||||
int len, ret;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* touch all the files in the build directory to avoid make time
|
||||
@@ -661,10 +668,8 @@ int build_kernel_module(Options *op, Package *p)
|
||||
|
||||
ui_log(op, "Cleaning kernel module build directory.");
|
||||
|
||||
len = strlen(p->kernel_module_build_directory) + 32;
|
||||
cmd = nvalloc(len);
|
||||
|
||||
snprintf(cmd, len, "cd %s; make clean", p->kernel_module_build_directory);
|
||||
cmd = nvstrcat("cd ", p->kernel_module_build_directory, "; ",
|
||||
op->utils[MAKE], " clean", NULL);
|
||||
|
||||
ret = run_command(op, cmd, &result, TRUE, 0, TRUE);
|
||||
free(result);
|
||||
@@ -757,7 +762,7 @@ int sign_kernel_module(Options *op, const char *build_directory,
|
||||
build_module_instances_parameter = nvstrdup("");
|
||||
}
|
||||
|
||||
cmd = nvstrcat("cd ", build_directory, "; make module-sign"
|
||||
cmd = nvstrcat("cd ", build_directory, "; ", op->utils[MAKE], " module-sign"
|
||||
" SYSSRC=", op->kernel_source_path,
|
||||
" SYSOUT=", op->kernel_output_path,
|
||||
" MODSECKEY=", op->module_signing_secret_key,
|
||||
@@ -885,7 +890,7 @@ static int build_kernel_interface_file(Options *op, const char *tmpdir,
|
||||
nvasprintf(" NV_BUILD_MODULE_INSTANCES=%d", NV_MAX_MODULE_INSTANCES);
|
||||
}
|
||||
|
||||
cmd = nvstrcat("cd ", tmpdir, "; make ",
|
||||
cmd = nvstrcat("cd ", tmpdir, "; ", op->utils[MAKE], " ",
|
||||
kernel_interface_filename,
|
||||
" SYSSRC=", op->kernel_source_path,
|
||||
" SYSOUT=", op->kernel_output_path,
|
||||
@@ -1364,21 +1369,28 @@ static int ignore_load_error(Options *op, Package *p,
|
||||
if (enokey || secureboot || module_sig_force || op->expert) {
|
||||
if (op->kernel_module_signed) {
|
||||
|
||||
ignore_error = ui_yes_no(op, TRUE,
|
||||
"The signed kernel module failed to "
|
||||
"load%s because the kernel does not "
|
||||
"trust any key which is capable of "
|
||||
"verifying the module signature. "
|
||||
"Would you like to install the signed "
|
||||
"kernel module anyway?\n\nNote that %s"
|
||||
"you will not be able to load the "
|
||||
"installed module until after a key "
|
||||
"that can verify the module signature "
|
||||
"is added to a key database that is "
|
||||
"trusted by the kernel. This will "
|
||||
"likely require rebooting your "
|
||||
"computer.", probable_reason,
|
||||
signature_related);
|
||||
const char *choices[2] = {
|
||||
"Install signed kernel module",
|
||||
"Abort installation"
|
||||
};
|
||||
|
||||
ignore_error = (ui_multiple_choice(op, choices, 2, 0,
|
||||
"The signed kernel module failed "
|
||||
"to load%s because the kernel "
|
||||
"does not trust any key which is "
|
||||
"capable of verifying the module "
|
||||
"signature. Would you like to "
|
||||
"install the signed kernel module "
|
||||
"anyway?\n\nNote that %syou "
|
||||
"will not be able to load the "
|
||||
"installed module until after a "
|
||||
"key that can verify the module "
|
||||
"signature is added to a key "
|
||||
"database that is trusted by the "
|
||||
"kernel. This will likely "
|
||||
"require rebooting your computer.",
|
||||
probable_reason,
|
||||
signature_related) == 0);
|
||||
} else {
|
||||
const char *secureboot_message, *dkms_message;
|
||||
|
||||
@@ -1876,11 +1888,16 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p)
|
||||
/* If we found one, ask expert users if they really want to use it */
|
||||
|
||||
if (info && op->expert) {
|
||||
if (!ui_yes_no(op, TRUE, "A precompiled kernel interface for the "
|
||||
"kernel '%s' has been found. Would you like to "
|
||||
"use this? (answering 'no' will require the "
|
||||
"installer to compile the interface)",
|
||||
info->description)) {
|
||||
const char *choices[2] = {
|
||||
"Use the precompiled interface",
|
||||
"Compile the interface"
|
||||
};
|
||||
|
||||
if (ui_multiple_choice(op, choices, 2, 0, "A precompiled kernel "
|
||||
"interface for the kernel '%s' has been found. "
|
||||
"Would you like use the precompiled interface, "
|
||||
"or would you like to compile the interface "
|
||||
"instead?", info->description) == 1) {
|
||||
free_precompiled(info);
|
||||
info = NULL;
|
||||
}
|
||||
@@ -2438,6 +2455,11 @@ int check_cc_version(Options *op, Package *p)
|
||||
int ret;
|
||||
Options dummyop;
|
||||
|
||||
const char *choices[2] = {
|
||||
"Ignore CC version check",
|
||||
"Abort installation"
|
||||
};
|
||||
|
||||
/*
|
||||
* If we're building/installing for a different kernel, then we
|
||||
* can't do the gcc version check (we don't have a /proc/version
|
||||
@@ -2461,14 +2483,13 @@ int check_cc_version(Options *op, Package *p)
|
||||
|
||||
if (ret) return TRUE;
|
||||
|
||||
ret = ui_yes_no(op, TRUE, "The CC version check failed:\n\n%s\n\n"
|
||||
"If you know what you are doing and want to "
|
||||
"ignore the gcc version check, select \"No\" to "
|
||||
"continue installation. Otherwise, select \"Yes\" to "
|
||||
"abort installation, set the CC environment variable to "
|
||||
"the name of the compiler used to compile your kernel, "
|
||||
"and restart installation. Abort now?", result);
|
||||
|
||||
ret = (ui_multiple_choice(op, choices, 2, 1, "The CC version check failed:"
|
||||
"\n\n%s\n\nIf you know what you are doing you "
|
||||
"can either ignore the CC version check and "
|
||||
"continue installation, or abort installation, "
|
||||
"set the CC environment variable to the name of "
|
||||
"the compiler used to compile your kernel, and "
|
||||
"restart installation.", result) == 1);
|
||||
nvfree(result);
|
||||
|
||||
if (!ret) setenv("IGNORE_CC_MISMATCH", "1", 1);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
330
misc.c
@@ -54,7 +54,6 @@
|
||||
#include "manifest.h"
|
||||
|
||||
static int check_symlink(Options*, const char*, const char*, const char*);
|
||||
static int check_file(Options*, const char*, const mode_t, const uint32);
|
||||
|
||||
|
||||
/*
|
||||
@@ -158,16 +157,22 @@ int check_runlevel(Options *op)
|
||||
nvfree(data);
|
||||
|
||||
if (runlevel == 's' || runlevel == 'S' || runlevel == '1') {
|
||||
ret = ui_yes_no(op, TRUE, "You appear to be running in runlevel 1; "
|
||||
"this may cause problems. For example: some "
|
||||
"distributions that use devfs do not run the devfs "
|
||||
"daemon in runlevel 1, making it difficult for "
|
||||
"`nvidia-installer` to correctly setup the kernel "
|
||||
"module configuration files. It is recommended "
|
||||
"that you quit installation now and switch to "
|
||||
"runlevel 3 (`telinit 3`) before installing.\n\n"
|
||||
"Quit installation now? (select 'No' to continue "
|
||||
"installation)");
|
||||
|
||||
const char *choices[2] = {
|
||||
"Continue installation",
|
||||
"Abort installation"
|
||||
};
|
||||
|
||||
ret = (ui_multiple_choice(op, choices, 2, 1, "You appear to be running "
|
||||
"in runlevel 1; this may cause problems. "
|
||||
"For example: some distributions that use "
|
||||
"devfs do not run the devfs daemon in "
|
||||
"runlevel 1, making it difficult for "
|
||||
"`nvidia-installer` to correctly setup the "
|
||||
"kernel module configuration files. It is "
|
||||
"recommended that you quit installation now "
|
||||
"and switch to runlevel 3 (`telinit 3`) "
|
||||
"before installing.") == 1);
|
||||
|
||||
if (ret) return FALSE;
|
||||
}
|
||||
@@ -487,67 +492,84 @@ int read_text_file(const char *filename, char **buf)
|
||||
* additional directories) for the utilities that the installer will
|
||||
* need to use. Returns TRUE on success and assigns the util fields
|
||||
* in the option struct; it returns FALSE on failure.
|
||||
*
|
||||
* XXX requiring ld may cause problems
|
||||
*/
|
||||
|
||||
#define EXTRA_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/bin/X11"
|
||||
|
||||
/*
|
||||
* Utils list; keep in sync with SystemUtils, SystemOptionalUtils, ModuleUtils
|
||||
* and DevelopUtils enum types
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const char *util;
|
||||
const char *package;
|
||||
} Util;
|
||||
|
||||
static const Util __utils[] = {
|
||||
|
||||
/* SystemUtils */
|
||||
[LDCONFIG] = { "ldconfig", "glibc" },
|
||||
[LDD] = { "ldd", "glibc" },
|
||||
[GREP] = { "grep", "grep" },
|
||||
[DMESG] = { "dmesg", "util-linux" },
|
||||
[TAIL] = { "tail", "coreutils" },
|
||||
[CUT] = { "cut", "coreutils" },
|
||||
[TR] = { "tr", "coreutils" },
|
||||
[SED] = { "sed", "sed" },
|
||||
|
||||
/* SystemOptionalUtils */
|
||||
[OBJCOPY] = { "objcopy", "binutils" },
|
||||
[CHCON] = { "chcon", "selinux" },
|
||||
[SELINUX_ENABLED] = { "selinuxenabled", "selinux" },
|
||||
[GETENFORCE] = { "getenforce", "selinux" },
|
||||
[EXECSTACK] = { "execstack", "selinux" },
|
||||
[PKG_CONFIG] = { "pkg-config", "pkg-config" },
|
||||
[XSERVER] = { "X", "xserver" },
|
||||
[OPENSSL] = { "openssl", "openssl" },
|
||||
|
||||
/* ModuleUtils */
|
||||
[INSMOD] = { "insmod", "module-init-tools' or 'kmod" },
|
||||
[MODPROBE] = { "modprobe", "module-init-tools' or 'kmod" },
|
||||
[RMMOD] = { "rmmod", "module-init-tools' or 'kmod" },
|
||||
[LSMOD] = { "lsmod", "module-init-tools' or 'kmod" },
|
||||
[DEPMOD] = { "depmod", "module-init-tools' or 'kmod" },
|
||||
|
||||
/* DevelopUtils */
|
||||
[CC] = { "cc", "gcc" },
|
||||
[MAKE] = { "make", "make" },
|
||||
[LD] = { "ld", "binutils" },
|
||||
|
||||
};
|
||||
|
||||
int find_system_utils(Options *op)
|
||||
{
|
||||
/* keep in sync with the SystemUtils enum type */
|
||||
const struct { const char *util, *package; } needed_utils[] = {
|
||||
{ "ldconfig", "glibc" },
|
||||
{ "ldd", "glibc" },
|
||||
{ "ld", "binutils" },
|
||||
{ "objcopy", "binutils" },
|
||||
{ "grep", "grep" },
|
||||
{ "dmesg", "util-linux" },
|
||||
{ "tail", "coreutils" },
|
||||
{ "cut", "coreutils" },
|
||||
{ "tr", "coreutils" },
|
||||
{ "sed", "sed" }
|
||||
};
|
||||
|
||||
/* keep in sync with the SystemOptionalUtils enum type */
|
||||
const struct { const char *util, *package; } optional_utils[] = {
|
||||
{ "chcon", "selinux" },
|
||||
{ "selinuxenabled", "selinux" },
|
||||
{ "getenforce", "selinux" },
|
||||
{ "execstack", "selinux" },
|
||||
{ "pkg-config", "pkg-config" },
|
||||
{ "X", "xserver" },
|
||||
{ "openssl", "openssl" }
|
||||
};
|
||||
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
ui_expert(op, "Searching for system utilities:");
|
||||
|
||||
/* search the PATH for each utility */
|
||||
|
||||
for (i = 0; i < MAX_SYSTEM_UTILS; i++) {
|
||||
op->utils[i] = find_system_util(needed_utils[i].util);
|
||||
for (i = MIN_SYSTEM_UTILS; i < MAX_SYSTEM_UTILS; i++) {
|
||||
op->utils[i] = find_system_util(__utils[i].util);
|
||||
if (!op->utils[i]) {
|
||||
ui_error(op, "Unable to find the system utility `%s`; please "
|
||||
"make sure you have the package '%s' installed. If "
|
||||
"you do have %s installed, then please check that "
|
||||
"`%s` is in your PATH.",
|
||||
needed_utils[i].util, needed_utils[i].package,
|
||||
needed_utils[i].package, needed_utils[i].util);
|
||||
__utils[i].util, __utils[i].package,
|
||||
__utils[i].package, __utils[i].util);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ui_expert(op, "found `%s` : `%s`",
|
||||
needed_utils[i].util, op->utils[i]);
|
||||
ui_expert(op, "found `%s` : `%s`", __utils[i].util, op->utils[i]);
|
||||
}
|
||||
|
||||
for (j = 0, i = MAX_SYSTEM_UTILS; i < MAX_SYSTEM_OPTIONAL_UTILS; i++, j++) {
|
||||
|
||||
op->utils[i] = find_system_util(optional_utils[j].util);
|
||||
if (op->utils[i]) {
|
||||
ui_expert(op, "found `%s` : `%s`",
|
||||
optional_utils[j].util, op->utils[i]);
|
||||
for (i = MIN_SYSTEM_OPTIONAL_UTILS; i < MAX_SYSTEM_OPTIONAL_UTILS; i++) {
|
||||
|
||||
op->utils[i] = find_system_util(__utils[i].util);
|
||||
if (op->utils[i]) {
|
||||
ui_expert(op, "found `%s` : `%s`", __utils[i].util, op->utils[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,30 +593,6 @@ int find_system_utils(Options *op)
|
||||
} /* find_system_utils() */
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *util;
|
||||
const char *package;
|
||||
} Util;
|
||||
|
||||
/* keep in sync with the ModuleUtils enum type */
|
||||
static Util __module_utils[] = {
|
||||
{ "insmod", "module-init-tools" },
|
||||
{ "modprobe", "module-init-tools" },
|
||||
{ "rmmod", "module-init-tools" },
|
||||
{ "lsmod", "module-init-tools" },
|
||||
{ "depmod", "module-init-tools" },
|
||||
};
|
||||
|
||||
/* keep in sync with the ModuleUtils enum type */
|
||||
static Util __module_utils_linux24[] = {
|
||||
{ "insmod", "modutils" },
|
||||
{ "modprobe", "modutils" },
|
||||
{ "rmmod", "modutils" },
|
||||
{ "lsmod", "modutils" },
|
||||
{ "depmod", "modutils" },
|
||||
};
|
||||
|
||||
/*
|
||||
* find_module_utils() - search the $PATH (as well as some common
|
||||
* additional directories) for the utilities that the installer will
|
||||
@@ -604,30 +602,25 @@ static Util __module_utils_linux24[] = {
|
||||
|
||||
int find_module_utils(Options *op)
|
||||
{
|
||||
int i, j;
|
||||
Util *needed_utils = __module_utils;
|
||||
|
||||
if (strncmp(get_kernel_name(op), "2.4", 3) == 0)
|
||||
needed_utils = __module_utils_linux24;
|
||||
int i;
|
||||
|
||||
ui_expert(op, "Searching for module utilities:");
|
||||
|
||||
/* search the PATH for each utility */
|
||||
|
||||
for (j=0, i = MAX_SYSTEM_OPTIONAL_UTILS; i < MAX_UTILS; i++, j++) {
|
||||
op->utils[i] = find_system_util(needed_utils[j].util);
|
||||
for (i = MIN_MODULE_UTILS; i < MAX_MODULE_UTILS; i++) {
|
||||
op->utils[i] = find_system_util(__utils[i].util);
|
||||
if (!op->utils[i]) {
|
||||
ui_error(op, "Unable to find the module utility `%s`; please "
|
||||
"make sure you have the package '%s' installed. If "
|
||||
"you do have %s installed, then please check that "
|
||||
"you do have '%s' installed, then please check that "
|
||||
"`%s` is in your PATH.",
|
||||
needed_utils[j].util, needed_utils[j].package,
|
||||
needed_utils[j].package, needed_utils[j].util);
|
||||
__utils[i].util, __utils[i].package,
|
||||
__utils[i].package, __utils[i].util);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ui_expert(op, "found `%s` : `%s`",
|
||||
needed_utils[j].util, op->utils[i]);
|
||||
ui_expert(op, "found `%s` : `%s`", __utils[i].util, op->utils[i]);
|
||||
};
|
||||
|
||||
return TRUE;
|
||||
@@ -744,18 +737,31 @@ int check_proc_modprobe_path(Options *op)
|
||||
* to build custom kernel interfaces are available.
|
||||
*/
|
||||
|
||||
static int check_development_tool(Options *op, int idx)
|
||||
{
|
||||
if (!op->utils[idx]) {
|
||||
ui_error(op, "Unable to find the development tool `%s` in "
|
||||
"your path; please make sure that you have the "
|
||||
"package '%s' installed. If %s is installed on your "
|
||||
"system, then please check that `%s` is in your "
|
||||
"PATH.",
|
||||
__utils[idx].util, __utils[idx].package,
|
||||
__utils[idx].package, __utils[idx].util);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ui_expert(op, "found `%s` : `%s`", __utils[idx].util, op->utils[idx]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int check_development_tools(Options *op, Package *p)
|
||||
{
|
||||
#define MAX_TOOLS 2
|
||||
const struct { char *tool, *package; } needed_tools[] = {
|
||||
{ "cc", "gcc" },
|
||||
{ "make", "make" }
|
||||
};
|
||||
|
||||
int i, ret;
|
||||
char *tool, *cmd, *CC, *result;
|
||||
char *cmd, *result;
|
||||
|
||||
CC = getenv("CC");
|
||||
op->utils[CC] = getenv("CC");
|
||||
|
||||
ui_expert(op, "Checking development tools:");
|
||||
|
||||
@@ -768,20 +774,13 @@ int check_development_tools(Options *op, Package *p)
|
||||
* checked below.
|
||||
*/
|
||||
|
||||
for (i = (CC != NULL) ? 1 : 0; i < MAX_TOOLS; i++) {
|
||||
tool = find_system_util(needed_tools[i].tool);
|
||||
if (!tool) {
|
||||
ui_error(op, "Unable to find the development tool `%s` in "
|
||||
"your path; please make sure that you have the "
|
||||
"package '%s' installed. If %s is installed on your "
|
||||
"system, then please check that `%s` is in your "
|
||||
"PATH.",
|
||||
needed_tools[i].tool, needed_tools[i].package,
|
||||
needed_tools[i].package, needed_tools[i].tool);
|
||||
for (i = (op->utils[CC] != NULL) ? MIN_DEVELOP_UTILS + 1 : MIN_DEVELOP_UTILS;
|
||||
i < MAX_DEVELOP_UTILS; i++) {
|
||||
|
||||
op->utils[i] = find_system_util(__utils[i].util);
|
||||
if (!check_development_tool(op, i)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ui_expert(op, "found `%s` : `%s`", needed_tools[i].tool, tool);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -795,12 +794,12 @@ int check_development_tools(Options *op, Package *p)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!CC) CC = "cc";
|
||||
if (!op->utils[CC]) op->utils[CC] = "cc";
|
||||
|
||||
ui_log(op, "Performing CC sanity check with CC=\"%s\".", CC);
|
||||
ui_log(op, "Performing CC sanity check with CC=\"%s\".", op->utils[CC]);
|
||||
|
||||
cmd = nvstrcat("sh ", p->kernel_module_build_directory,
|
||||
"/conftest.sh ", CC, " ", CC, " ",
|
||||
"/conftest.sh ", op->utils[CC], " ", op->utils[CC], " ",
|
||||
"DUMMY_SOURCE DUMMY_OUTPUT ",
|
||||
"cc_sanity_check just_msg", NULL);
|
||||
|
||||
@@ -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
19
misc.h
@@ -29,6 +29,19 @@
|
||||
|
||||
#include "nvidia-installer.h"
|
||||
#include "command-list.h"
|
||||
#include "user-interface.h"
|
||||
|
||||
/*
|
||||
* Enumeration to identify whether the execution of a distro hook script has
|
||||
* succeeded, failed or the script has not actually been executed
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
HOOK_SCRIPT_FAIL = 0,
|
||||
HOOK_SCRIPT_SUCCESS,
|
||||
HOOK_SCRIPT_NO_RUN,
|
||||
} HookScriptStatus;
|
||||
|
||||
|
||||
typedef enum {
|
||||
ELF_INVALID_FILE,
|
||||
@@ -52,6 +65,7 @@ int find_module_utils(Options *op);
|
||||
int check_selinux(Options *op);
|
||||
int check_proc_modprobe_path(Options *op);
|
||||
int check_development_tools(Options *op, Package *p);
|
||||
int check_precompiled_kernel_interface_tools(Options *op);
|
||||
char *extract_version_string(const char *str);
|
||||
int continue_after_error(Options *op, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
|
||||
int do_install(Options *op, Package *p, CommandList *c);
|
||||
@@ -60,6 +74,8 @@ void should_install_compat32_files(Options *op, Package *p);
|
||||
void should_install_vdpau_wrapper(Options *op, Package *p);
|
||||
void should_install_uvm(Options *op, Package *p);
|
||||
void check_installed_files_from_package(Options *op, Package *p);
|
||||
int check_installed_file(Options*, const char*, const mode_t, const uint32,
|
||||
ui_message_func *logwarn);
|
||||
int tls_test(Options *op, int compat_32_libs);
|
||||
int check_runtime_configuration(Options *op, Package *p);
|
||||
void collapse_multiple_slashes(char *s);
|
||||
@@ -69,13 +85,12 @@ int check_for_running_x(Options *op);
|
||||
int check_for_modular_xorg(Options *op);
|
||||
int check_for_nvidia_graphics_devices(Options *op, Package *p);
|
||||
int run_nvidia_xconfig(Options *op, int restore);
|
||||
int run_distro_hook(Options *op, const char *hook);
|
||||
HookScriptStatus run_distro_hook(Options *op, const char *hook);
|
||||
int check_for_alternate_install(Options *op);
|
||||
int check_for_nouveau(Options *op);
|
||||
int dkms_module_installed(Options *op, const char *version);
|
||||
int dkms_install_module(Options *op, const char *version, const char *kernel);
|
||||
int dkms_remove_module(Options *op, const char *version);
|
||||
int unprelink(Options *op, const char *filename);
|
||||
int verify_crc(Options *op, const char *filename, unsigned int crc,
|
||||
unsigned int *actual_crc);
|
||||
int secure_boot_enabled(void);
|
||||
|
174
ncurses-ui.c
174
ncurses-ui.c
@@ -161,6 +161,8 @@ static void nv_ncurses_command_output (Options*, const char*);
|
||||
static int nv_ncurses_approve_command_list(Options*, CommandList*,
|
||||
const char*);
|
||||
static int nv_ncurses_yes_no (Options*, const int, const char*);
|
||||
static int nv_ncurses_multiple_choice (Options *, const char*,
|
||||
const char **, int, int);
|
||||
static void nv_ncurses_status_begin (Options*, const char*,
|
||||
const char*);
|
||||
static void nv_ncurses_status_update (Options*, const float,
|
||||
@@ -189,6 +191,9 @@ static void nv_ncurses_destroy_region(RegionStruct *);
|
||||
static void nv_ncurses_draw_button(DataStruct *, RegionStruct *, int, int,
|
||||
int, int, const char *, bool, bool);
|
||||
static void nv_ncurses_erase_button(RegionStruct *, int, int, int, int);
|
||||
static void draw_buttons(DataStruct *d, const char **buttons, int num_buttons,
|
||||
int button, int button_w, const int *buttons_x,
|
||||
int button_y);
|
||||
|
||||
|
||||
/* helper functions for drawing regions and stuff */
|
||||
@@ -247,6 +252,7 @@ InstallerUI ui_dispatch_table = {
|
||||
nv_ncurses_command_output,
|
||||
nv_ncurses_approve_command_list,
|
||||
nv_ncurses_yes_no,
|
||||
nv_ncurses_multiple_choice,
|
||||
nv_ncurses_paged_prompt,
|
||||
nv_ncurses_status_begin,
|
||||
nv_ncurses_status_update,
|
||||
@@ -802,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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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() */
|
||||
|
@@ -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"
|
||||
|
||||
|
174
stream-ui.c
174
stream-ui.c
@@ -33,6 +33,7 @@
|
||||
#include "misc.h"
|
||||
#include "files.h"
|
||||
#include "common-utils.h"
|
||||
#include "msg.h"
|
||||
|
||||
/* prototypes of each of the stream ui functions */
|
||||
|
||||
@@ -45,6 +46,8 @@ void stream_message (Options*, int level, const char*);
|
||||
void stream_command_output (Options*, const char*);
|
||||
int stream_approve_command_list(Options*, CommandList*, const char*);
|
||||
int stream_yes_no (Options*, const int, const char*);
|
||||
int stream_multiple_choice (Options *op, const char *, const char **,
|
||||
int, int);
|
||||
int stream_paged_prompt (Options *op, const char *, const char *,
|
||||
const char *, const char **, int, int);
|
||||
void stream_status_begin (Options*, const char*, const char*);
|
||||
@@ -62,6 +65,7 @@ InstallerUI stream_ui_dispatch_table = {
|
||||
stream_command_output,
|
||||
stream_approve_command_list,
|
||||
stream_yes_no,
|
||||
stream_multiple_choice,
|
||||
stream_paged_prompt,
|
||||
stream_status_begin,
|
||||
stream_status_update,
|
||||
@@ -148,9 +152,10 @@ int stream_init(Options *op, FormatTextRows format_text_rows)
|
||||
|
||||
if (!op->silent) {
|
||||
|
||||
fmtout("");
|
||||
fmtout("Welcome to the NVIDIA Software Installer for Unix/Linux");
|
||||
fmtout("");
|
||||
nv_info_msg(NULL, "");
|
||||
nv_info_msg(NULL, "Welcome to the NVIDIA Software Installer for "
|
||||
"Unix/Linux");
|
||||
nv_info_msg(NULL, "");
|
||||
|
||||
/* register the SIGWINCH signal handler */
|
||||
|
||||
@@ -185,8 +190,8 @@ char *stream_get_input(Options *op, const char *def, const char *msg)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
fmt(stdout, NULL, "");
|
||||
fmt(stdout, NULL, "%s", msg);
|
||||
nv_info_msg(NULL, "");
|
||||
nv_info_msg(NULL, "%s", msg);
|
||||
fprintf(stdout, " [default: '%s']: ", def);
|
||||
fflush(stdout);
|
||||
|
||||
@@ -214,17 +219,18 @@ int stream_display_license(Options *op, const char *license)
|
||||
{
|
||||
char *str;
|
||||
|
||||
fmtout("");
|
||||
fmtout("Please read the following LICENSE and type \""
|
||||
"accept\" followed by the Enter key to accept the license, or "
|
||||
"type anything else to not accept and exit nvidia-installer.");
|
||||
fmtout("");
|
||||
nv_info_msg(NULL, "");
|
||||
nv_info_msg(NULL, "Please read the following LICENSE and type \""
|
||||
"accept\" followed by the Enter key to accept the "
|
||||
"license, or type anything else to not accept and "
|
||||
"exit nvidia-installer.");
|
||||
nv_info_msg(NULL, "");
|
||||
|
||||
fmtout("________");
|
||||
fmtout("");
|
||||
nv_info_msg(NULL, "________");
|
||||
nv_info_msg(NULL, "");
|
||||
printf("%s", license);
|
||||
fmtout("________");
|
||||
fmtout("");
|
||||
nv_info_msg(NULL, "________");
|
||||
nv_info_msg(NULL, "");
|
||||
|
||||
printf("Accept? (Type \"Accept\" to accept, or anything else to abort): ");
|
||||
fflush(stdout);
|
||||
@@ -274,9 +280,15 @@ void stream_message(Options *op, const int level, const char *msg)
|
||||
|
||||
if ((level == NV_MSG_LEVEL_LOG) && (d->status_active)) return;
|
||||
|
||||
if (msg_attrs[level].newline) fmt(msg_attrs[level].stream, NULL, "");
|
||||
fmt(msg_attrs[level].stream, msg_attrs[level].prefix, "%s", msg);
|
||||
if (msg_attrs[level].newline) fmt(msg_attrs[level].stream, NULL, "");
|
||||
if (msg_attrs[level].newline) {
|
||||
nv_info_msg_to_file(msg_attrs[level].stream, NULL, "");
|
||||
}
|
||||
nv_info_msg_to_file(msg_attrs[level].stream,
|
||||
msg_attrs[level].prefix,
|
||||
"%s", msg);
|
||||
if (msg_attrs[level].newline) {
|
||||
nv_info_msg_to_file(msg_attrs[level].stream, NULL, "");
|
||||
}
|
||||
|
||||
} /* stream_message() */
|
||||
|
||||
@@ -295,7 +307,7 @@ void stream_command_output(Options *op, const char *msg)
|
||||
|
||||
if ((!op->expert) || (d->status_active)) return;
|
||||
|
||||
fmtoutp(" ", "%s", msg);
|
||||
nv_info_msg(" ", "%s", msg);
|
||||
|
||||
} /* stream_command_output() */
|
||||
|
||||
@@ -314,10 +326,10 @@ int stream_approve_command_list(Options *op, CommandList *cl,
|
||||
char *perms;
|
||||
const char *prefix = " --> ";
|
||||
|
||||
fmtout("");
|
||||
fmtout("The following operations will be performed to install the %s:",
|
||||
descr);
|
||||
fmtout("");
|
||||
nv_info_msg(NULL, "");
|
||||
nv_info_msg(NULL, "The following operations will be performed to install the %s:",
|
||||
descr);
|
||||
nv_info_msg(NULL, "");
|
||||
|
||||
for (i = 0; i < cl->num; i++) {
|
||||
c = &cl->cmds[i];
|
||||
@@ -326,37 +338,37 @@ int stream_approve_command_list(Options *op, CommandList *cl,
|
||||
|
||||
case INSTALL_CMD:
|
||||
perms = mode_to_permission_string(c->mode);
|
||||
fmtoutp(prefix, "install the file '%s' as '%s' with "
|
||||
"permissions '%s'", c->s0, c->s1, perms);
|
||||
nv_info_msg(prefix, "install the file '%s' as '%s' with "
|
||||
"permissions '%s'", c->s0, c->s1, perms);
|
||||
free(perms);
|
||||
if (c->s2) {
|
||||
fmtoutp(prefix, "execute the command `%s`", c->s2);
|
||||
nv_info_msg(prefix, "execute the command `%s`", c->s2);
|
||||
}
|
||||
break;
|
||||
|
||||
case RUN_CMD:
|
||||
fmtoutp(prefix, "execute the command `%s`", c->s0);
|
||||
nv_info_msg(prefix, "execute the command `%s`", c->s0);
|
||||
break;
|
||||
|
||||
case SYMLINK_CMD:
|
||||
fmtoutp(prefix, "create a symbolic link '%s' to '%s'",
|
||||
c->s0, c->s1);
|
||||
nv_info_msg(prefix, "create a symbolic link '%s' to '%s'",
|
||||
c->s0, c->s1);
|
||||
break;
|
||||
|
||||
case BACKUP_CMD:
|
||||
fmtoutp(prefix, "back up the file '%s'", c->s0);
|
||||
nv_info_msg(prefix, "back up the file '%s'", c->s0);
|
||||
break;
|
||||
|
||||
case DELETE_CMD:
|
||||
fmtoutp(prefix, "delete file '%s'", c->s0);
|
||||
nv_info_msg(prefix, "delete file '%s'", c->s0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
fmterr("Error in CommandList! (cmd: %d; s0: '%s';"
|
||||
"s1: '%s'; s2: '%s'; mode: %04o)",
|
||||
c->cmd, c->s0, c->s1, c->s2, c->mode);
|
||||
fmterr("Aborting installation.");
|
||||
nv_error_msg("Error in CommandList! (cmd: %d; s0: '%s';"
|
||||
"s1: '%s'; s2: '%s'; mode: %04o)",
|
||||
c->cmd, c->s0, c->s1, c->s2, c->mode);
|
||||
nv_error_msg("Aborting installation.");
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
@@ -366,7 +378,7 @@ int stream_approve_command_list(Options *op, CommandList *cl,
|
||||
|
||||
if (!stream_yes_no(op, TRUE, "\nIs this acceptable? (answering 'no' will "
|
||||
"abort installation)")) {
|
||||
fmterr("Command list not accepted; exiting installation.");
|
||||
nv_error_msg("Command list not accepted; exiting installation.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -386,8 +398,8 @@ int stream_yes_no(Options *op, const int def, const char *msg)
|
||||
char *buf;
|
||||
int eof, ret = def;
|
||||
|
||||
fmt(stdout, NULL, "");
|
||||
fmt(stdout, NULL, "%s", msg);
|
||||
nv_info_msg(NULL, "");
|
||||
nv_info_msg(NULL, "%s", msg);
|
||||
if (def) fprintf(stdout, " [default: (Y)es]: ");
|
||||
else fprintf(stdout, " [default: (N)o]: ");
|
||||
fflush(stdout);
|
||||
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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__ */
|
||||
|
1
utils.mk
1
utils.mk
@@ -114,6 +114,7 @@ endif
|
||||
TARGET_ARCH_ABI ?=
|
||||
|
||||
OUTPUTDIR ?= _out/$(TARGET_OS)_$(TARGET_ARCH)
|
||||
OUTPUTDIR_ABSOLUTE ?= $(CURDIR)/$(OUTPUTDIR)
|
||||
|
||||
NV_QUIET_COMMAND_REMOVED_TARGET_PREFIX ?=
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
NVIDIA_VERSION = 331.38
|
||||
NVIDIA_VERSION = 334.16
|
||||
|
Reference in New Issue
Block a user