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