diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2014-11-13 08:51:28 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2014-11-13 08:51:28 -0800 |
commit | 6765fcac47d7270b8ac1eea1978de484d658bde1 (patch) | |
tree | 76f932f6773461276d7a278776befaf2c37b3b8c | |
parent | 2574fdfc9c20e9372ffda4f8601a0322bd408c4e (diff) |
346.16346.16
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | backup.c | 107 | ||||
-rw-r--r-- | command-list.c | 495 | ||||
-rw-r--r-- | common-utils/common-utils.c | 98 | ||||
-rw-r--r-- | common-utils/common-utils.h | 5 | ||||
-rw-r--r-- | common-utils/nvgetopt.c | 16 | ||||
-rw-r--r-- | crc.c | 36 | ||||
-rw-r--r-- | dist-files.mk | 2 | ||||
-rw-r--r-- | files.c | 897 | ||||
-rw-r--r-- | files.h | 5 | ||||
-rw-r--r-- | install-from-cwd.c | 388 | ||||
-rw-r--r-- | kernel.c | 130 | ||||
-rw-r--r-- | manifest.c | 124 | ||||
-rw-r--r-- | misc.c | 377 | ||||
-rw-r--r-- | misc.h | 6 | ||||
-rw-r--r-- | ncurses-ui.c | 2 | ||||
-rw-r--r-- | nvidia-installer.c | 37 | ||||
-rw-r--r-- | nvidia-installer.h | 89 | ||||
-rw-r--r-- | option_table.h | 42 | ||||
-rw-r--r-- | precompiled.c | 49 | ||||
-rw-r--r-- | sanity.c | 48 | ||||
-rw-r--r-- | sanity.h | 1 | ||||
-rw-r--r-- | snarf-ftp.c | 2 | ||||
-rwxr-xr-x | tls_test_Linux-ia64 | bin | 14162 -> 0 bytes | |||
-rwxr-xr-x | tls_test_dso_Linux-ia64.so | bin | 10260 -> 0 bytes | |||
-rw-r--r-- | update.c | 11 | ||||
-rw-r--r-- | user-interface.c | 4 | ||||
-rw-r--r-- | utils.mk | 90 | ||||
-rw-r--r-- | version.mk | 2 |
29 files changed, 1751 insertions, 1319 deletions
@@ -103,7 +103,6 @@ OPTIONS_1_INC = $(OUTPUTDIR)/options.1.inc ifeq ($(TARGET_OS)-$(TARGET_ARCH), Linux-x86_64) TLS_MODEL = initial-exec PIC = -fPIC - CFLAGS += -DNV_X86_64 # Only Linux-x86_64 needs the tls_test_32 files COMPAT_32_SRC = $(TLS_TEST_32_C) $(TLS_TEST_DSO_32_C) \ $(RTLD_TEST_32_C) @@ -308,9 +307,9 @@ tls_test: tls_test.c # rule to rebuild rtld_test; a precompiled rtld_test is distributed with # nvidia-installer to simplify x86-64 builds. -rebuild_rtld_test: rtld_test.c - gcc -Wall -O2 -fomit-frame-pointer -o $(RTLD_TEST) -lGL $< - strip $(RTLD_TEST) +rebuild_rtld_test: rtld_test.c $(CONFIG_H) + $(call quiet_cmd,LINK) $(CFLAGS) $(LDFLAGS) $(BIN_LDFLAGS) -o $(RTLD_TEST) -lGL $< + $(call quiet_cmd,STRIP_CMD) $(RTLD_TEST) # dummy rule to override implicit rule that builds dls_test from # rtld_test.c @@ -141,7 +141,7 @@ int init_backup(Options *op, Package *p) /* remove the directory, if it already exists */ - if (directory_exists(op, BACKUP_DIRECTORY)) { + if (directory_exists(BACKUP_DIRECTORY)) { if (!remove_directory(op, BACKUP_DIRECTORY)) { return FALSE; } @@ -208,7 +208,7 @@ int do_backup(Options *op, const char *filename) { int len, ret, ret_val; struct stat stat_buf; - char *tmp; + char *tmp = NULL; FILE *log; uint32 crc; @@ -251,7 +251,6 @@ int do_backup(Options *op, const char *filename) fprintf(log, "%u %04o %d %d\n", crc, stat_buf.st_mode, stat_buf.st_uid, stat_buf.st_gid); - free(tmp); backup_file_number++; } else if (S_ISLNK(stat_buf.st_mode)) { tmp = get_symlink_target(op, filename); @@ -267,7 +266,6 @@ int do_backup(Options *op, const char *filename) fprintf(log, "%s\n", tmp); fprintf(log, "%04o %d %d\n", stat_buf.st_mode, stat_buf.st_uid, stat_buf.st_gid); - free(tmp); } else if (S_ISDIR(stat_buf.st_mode)) { /* XXX IMPLEMENT ME: recursive moving of a directory */ @@ -284,6 +282,8 @@ int do_backup(Options *op, const char *filename) done: + nvfree(tmp); + /* close the log file */ if (fclose(log) != 0) { @@ -506,7 +506,7 @@ int log_mkdir(Options *op, const char *dirs) * is within BACKUP_DIRECTORY, so the below fopen(3) call depends on * the existence of BACKUP_DIRECTORY */ - if (!directory_exists(op, BACKUP_DIRECTORY) && + if (!directory_exists(BACKUP_DIRECTORY) && !mkdir_recursive(op, BACKUP_DIRECTORY, BACKUP_DIRECTORY_PERMS, FALSE)) { return FALSE; } @@ -832,27 +832,29 @@ static int do_uninstall(Options *op, const char *version) /* XXX what to do if this fails?... nothing */ } - /* - * attempt to unload the kernel module(s), but don't abort if this fails: - * the kernel may not have been configured with support for module - * unloading or the user might have unloaded it themselves or the module - * might not have existed at all. - */ + if (!op->skip_module_unload) { + /* + * attempt to unload the kernel module(s), but don't abort if this + * fails: the kernel may not have been configured with support for + * module unloading or the user might have unloaded it themselves or the + * module might not have existed at all. + */ - unload_nvidia_module(op, "-uvm"); + unload_nvidia_module(op, "-uvm"); - unload_nvidia_module(op, ""); + unload_nvidia_module(op, ""); - for (i = 0; i < NV_MAX_MODULE_INSTANCES; i++) { - char num[5]; - memset(num, 0, sizeof(num)); - snprintf(num, sizeof(num), "%d", i); - num[sizeof(num) - 1] = '\0'; + for (i = 0; i < NV_MAX_MODULE_INSTANCES; i++) { + char num[5]; + memset(num, 0, sizeof(num)); + snprintf(num, sizeof(num), "%d", i); + num[sizeof(num) - 1] = '\0'; - unload_nvidia_module(op, num); - } + unload_nvidia_module(op, num); + } - unload_nvidia_module(op, "-frontend"); + unload_nvidia_module(op, "-frontend"); + } run_distro_hook(op, "post-uninstall"); @@ -902,13 +904,13 @@ static BackupInfo *read_backup_log_file(Options *op) if (fstat(fd, &stat_buf) == -1) { ui_error(op, "Failure getting file properties for %s (%s).", BACKUP_LOG, strerror(errno)); - return NULL; + goto pre_map_fail; } if ((stat_buf.st_mode & PERM_MASK) != BACKUP_LOG_PERMS) { ui_error(op, "The file permissions of %s have been changed since " "the file was written!", BACKUP_LOG); - return NULL; + goto pre_map_fail; } /* map the file */ @@ -1033,11 +1035,14 @@ static BackupInfo *read_backup_log_file(Options *op) ui_status_end(op, "error."); munmap(buf, stat_buf.st_size); - close(fd); ui_error(op, "Error while parsing line %d of '%s'.", line_num, BACKUP_LOG); - if (b) free(b); + nvfree(b); + + pre_map_fail: + + close(fd); return NULL; } /* read_backup_log_file() */ @@ -1376,18 +1381,15 @@ int uninstall_existing_driver(Options *op, const int interactive) } if (interactive && op->uninstall) { - ret = ui_yes_no(op, FALSE, - "If you plan to no longer use the NVIDIA driver, you " - "should make sure that no X screens are configured to " - "use the NVIDIA X driver in your X configuration file. " - "If you used nvidia-xconfig to configure X, it may have " - "created a backup of your original configuration. Would " - "you like to run `nvidia-xconfig --restore-original-" - "backup` to attempt restoration of the original X " - "configuration file?"); - if (ret) { - run_nvidia_xconfig(op, TRUE); - } + const char *msg = "If you plan to no longer use the NVIDIA driver, you " + "should make sure that no X screens are configured to " + "use the NVIDIA X driver in your X configuration file. " + "If you used nvidia-xconfig to configure X, it may have " + "created a backup of your original configuration. Would " + "you like to run `nvidia-xconfig --restore-original-" + "backup` to attempt restoration of the original X " + "configuration file?"; + run_nvidia_xconfig(op, TRUE, msg, FALSE); } ret = do_uninstall(op, version); @@ -1426,13 +1428,40 @@ int run_existing_uninstaller(Options *op) * uninstall log location: older installers may not do so implicitly. */ char *uninstall_cmd = nvstrcat(uninstaller, " -s --log-file-name=" DEFAULT_UNINSTALL_LOG_FILE_NAME, NULL); - char *data; + char *data = NULL; int ret; ui_log(op, "Uninstalling the previous installation with %s.", uninstaller); - ret = run_command(op, uninstall_cmd, &data, FALSE, 0, TRUE); + if (!op->no_kernel_module && !op->kernel_name) { + /* + * Attempt to run the uninstaller with the --skip-module-unload + * option first. If that fails, fall back to running it without + * that option. + * + * We don't want the uninstaller to unload the module because this + * instance of the installer already unloaded the old module and + * loaded the new one. + */ + char *uninstall_skip_unload_cmd = + nvstrcat(uninstall_cmd, " --skip-module-unload", NULL); + ret = run_command(op, uninstall_skip_unload_cmd, NULL, FALSE, 0, TRUE); + nvfree(uninstall_skip_unload_cmd); + } else { + /* + * If installing the kernel module was skipped or we're + * building/installing for a different kernel, then the new kernel + * module wasn't automatically loaded and we should unload whichever + * one is loaded now. + */ + ret = 1; + } + + if (ret) { + /* Try again without --skip-module-unload */ + ret = run_command(op, uninstall_cmd, &data, FALSE, 0, TRUE); + } nvfree(uninstall_cmd); diff --git a/command-list.c b/command-list.c index 1ff75e7..a35c7a6 100644 --- a/command-list.c +++ b/command-list.c @@ -47,18 +47,6 @@ static void free_file_list(FileList* l); -static void find_conflicting_xfree86_libraries(Options *, - const char *, - FileList *); - -static void find_conflicting_xfree86_libraries_fullpath(Options *op, - char *, - FileList *l); - -static void find_conflicting_opengl_libraries(Options *, - const char *, - FileList *); - static void find_conflicting_kernel_modules(Options *op, Package *p, FileList *l); @@ -84,6 +72,110 @@ typedef struct { char *name; /* name to find: NULL to end the list */ } NoRecursionDirectory; +static void find_conflicting_files(Options *op, + char *path, + ConflictingFileInfo *files, + FileList *l, + const NoRecursionDirectory *skipdirs); + + +/* + * Check if a path already exists in the path list, or is a subdirectory of + * a path that exists in the path list, or is a symlink to or symlink target + * of a directory that exists in the path list. + */ +static int path_already_exists(char ***paths, int count, const char *path) +{ + int i; + + for (i = 0; i < count; i++) { + int is_subdir = FALSE; + + is_subdirectory((*paths)[i], path, &is_subdir); + + if (is_subdir) { + return TRUE; + } + } + + return FALSE; +} + +/* + * Add a new path to the list of paths to search, provided that it exists + * and is not redundant. + * XXX we only check to see if the new directory is a subdirectory of any + * existing directory, and not the other way around. + */ +static void add_search_path(char ***paths, int *count, const char *path) +{ + if (directory_exists(path) && !path_already_exists(paths, *count, path)) { + *paths = nvrealloc(*paths, sizeof(char *) * (*count + 1)); + (*paths)[*count] = nvstrdup(path); + (*count)++; + } +} + +/* + * Given a path, add the subdirectories "/lib", "/lib32", and "/lib64" to the + * list of paths to search. + */ +static void add_search_paths(char ***paths, int *count, const char *pathbase) +{ + int i; + const char *subdirs[] = { + "/lib", + "/lib32", + "/lib64", + }; + + for (i = 0; i < ARRAY_LEN(subdirs); i++) { + char *path = nvstrcat(pathbase, subdirs[i], NULL); + add_search_path(paths, count, path); + nvfree(path); + } +} + +/* + * Build the list of paths under which to search for conflicting files. + * Returns the number of paths added to the search list. + */ +static int get_conflicting_search_paths(const Options *op, char ***paths) +{ + int ret = 0; + + *paths = NULL; + + add_search_paths(paths, &ret, DEFAULT_X_PREFIX); + add_search_paths(paths, &ret, XORG7_DEFAULT_X_PREFIX); + add_search_paths(paths, &ret, op->x_prefix); + add_search_paths(paths, &ret, DEFAULT_OPENGL_PREFIX); + add_search_paths(paths, &ret, op->opengl_prefix); + add_search_path(paths, &ret, op->x_module_path); + add_search_path(paths, &ret, op->x_library_path); + +#if defined(NV_X86_64) + if (op->compat32_chroot != NULL) { + int i; + char *subdirs[] = { + DEFAULT_X_PREFIX, + op->x_prefix, + DEFAULT_OPENGL_PREFIX, + op->opengl_prefix, + op->compat32_prefix, + }; + + for (i = 0; i < ARRAY_LEN(subdirs); i++) { + char *path = nvstrcat(op->compat32_chroot, "/", subdirs[i], NULL); + add_search_paths(paths, &ret, path); + nvfree(path); + } + } +#endif + + return ret; +} + /* * build_command_list() - construct a list of all the things to do @@ -149,70 +241,30 @@ CommandList *build_command_list(Options *op, Package *p) } if (!op->kernel_module_only) { + char **paths; + int numpaths, i; + /* - * Note that searching the various paths may produce duplicate - * entries for conflicting files; this is OK because we will take - * care of these duplicates in condense_file_list(). + * stop recursing into any "nvidia-cg-toolkit" + * directory to prevent libGL.so.1 from being deleted + * (see bug 843595). */ + static const NoRecursionDirectory skipdirs[] = { + { -1, "nvidia-cg-toolkit" }, + { 0, NULL } + }; - ui_status_begin(op, "Searching for conflicting X files:", "Searching"); - - ui_status_update(op, 0.16f, DEFAULT_X_PREFIX); - find_conflicting_xfree86_libraries(op, DEFAULT_X_PREFIX, l); - ui_status_update(op, 0.32f, XORG7_DEFAULT_X_PREFIX); - find_conflicting_xfree86_libraries(op, XORG7_DEFAULT_X_PREFIX, l); - ui_status_update(op, 0.48f, "%s", op->x_prefix); - find_conflicting_xfree86_libraries(op, op->x_prefix, l); + numpaths = get_conflicting_search_paths(op, &paths); - ui_status_update(op, 0.64f, "%s", op->x_module_path); - find_conflicting_xfree86_libraries_fullpath(op, op->x_module_path, l); - ui_status_update(op, 0.80f, "%s", op->x_library_path); - find_conflicting_xfree86_libraries_fullpath(op, op->x_library_path, l); - - ui_status_end(op, "done."); + ui_status_begin(op, "Searching for conflicting files:", "Searching"); - ui_status_begin(op, "Searching for conflicting OpenGL files:", "Searching"); - - ui_status_update(op, 0.20f, DEFAULT_X_PREFIX); - find_conflicting_opengl_libraries(op, DEFAULT_X_PREFIX, l); - ui_status_update(op, 0.40f, "%s", op->x_prefix); - find_conflicting_opengl_libraries(op, op->x_prefix, l); - ui_status_update(op, 0.60f, DEFAULT_OPENGL_PREFIX); - find_conflicting_opengl_libraries(op, DEFAULT_OPENGL_PREFIX, l); - ui_status_update(op, 0.80f, "%s", op->opengl_prefix); - find_conflicting_opengl_libraries(op, op->opengl_prefix, l); + for (i = 0; i < numpaths; i++) { + ui_status_update(op, (i + 1.0f) / numpaths, "Searching: %s", paths[i]); + find_conflicting_files(op, paths[i], p->conflicting_files, l, + skipdirs); + } ui_status_end(op, "done."); - -#if defined(NV_X86_64) - if (op->compat32_chroot != NULL) { - char *prefix; - - ui_status_begin(op, "Searching for conflicting compat32 files:", "Searching"); - - prefix = nvstrcat(op->compat32_chroot, DEFAULT_X_PREFIX, NULL); - ui_status_update(op, 0.20f, "%s", prefix); - find_conflicting_opengl_libraries(op, prefix, l); - nvfree(prefix); - - prefix = nvstrcat(op->compat32_chroot, op->x_prefix, NULL); - ui_status_update(op, 0.40f, "%s", prefix); - find_conflicting_opengl_libraries(op, prefix, l); - nvfree(prefix); - - prefix = nvstrcat(op->compat32_chroot, DEFAULT_OPENGL_PREFIX, NULL); - ui_status_update(op, 0.60f, "%s", prefix); - find_conflicting_opengl_libraries(op, prefix, l); - nvfree(prefix); - - prefix = nvstrcat(op->compat32_chroot, op->compat32_prefix, NULL); - ui_status_update(op, 0.80f, "%s", prefix); - find_conflicting_opengl_libraries(op, prefix, l); - nvfree(prefix); - - ui_status_end(op, "done."); - } -#endif /* NV_X86_64 */ } /* @@ -369,16 +421,6 @@ CommandList *build_command_list(Options *op, Package *p) nvfree(tmp); } - /* - * if on SuSE or United Linux, also do `/usr/bin/chrc.config - * SCRIPT_3D no` - */ - - if (((op->distro == SUSE) || (op->distro == UNITED_LINUX)) && - (access("/usr/bin/chrc.config", X_OK) == 0)) { - add_command(c, RUN_CMD, "/usr/bin/chrc.config SCRIPT_3D no"); - } - /* free the FileList */ free_file_list(l); @@ -569,197 +611,6 @@ int execute_command_list(Options *op, CommandList *c, */ -/* - * CONFLICT_ARCH_ALL: file always conflicts, regardless of arch - * CONFLICT_ARCH_32: file only conflicts if its arch is 32 bit - * CONFLICT_ARCH_64: file only conflicts if its arch is 64 bit - */ - -typedef enum { - CONFLICT_ARCH_ALL, - CONFLICT_ARCH_32, - CONFLICT_ARCH_64, -} ConflictArch; - - -typedef struct { - const char *name; - int len; - - /* - * if requiredString is non-NULL, then a file must have this - * string in order to be considered a conflicting file; we use - * this to only consider "libglx.*" files conflicts if they have - * the string "glxModuleData". - */ - - const char *requiredString; - - ConflictArch conflictArch; -} ConflictingFileInfo; - -static void find_conflicting_files(Options *op, - char *path, - ConflictingFileInfo *files, - FileList *l, - const NoRecursionDirectory *skipdirs); - -static void find_conflicting_libraries(Options *op, - const char *prefix, - ConflictingFileInfo *libs, - FileList *l); - -static ConflictingFileInfo __xfree86_opengl_libs[] = { - - /* Conflicting OpenGL libraries */ - - { "libnvidia-glcore.", 17, /* strlen("libnvidia-glcore.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libGL.", 6, /* strlen("libGL.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libGLwrapper.", 13, /* strlen("libGLwrapper.") */ - NULL, CONFLICT_ARCH_ALL }, - - /* Conflicting X extensions */ - - { "libglx.", 7, /* strlen("libglx.") */ - "glxModuleData", CONFLICT_ARCH_ALL }, - { "libglamoregl.", 13, /* strlen("libglamoregl.") */ - NULL, CONFLICT_ARCH_ALL }, - - /* Conflicting EGL libraries: */ - - { "libEGL.", 7, /* strlen("libEGL.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libGLESv1_CM.", 13, /* strlen("libGLESv1_CM." */ - NULL, CONFLICT_ARCH_ALL }, - { "libGLESv2.", 10, /* strlen("libGLESv2." */ - NULL, CONFLICT_ARCH_ALL }, - { NULL, 0, NULL, CONFLICT_ARCH_ALL } -}; - -static ConflictingFileInfo __xfree86_non_opengl_libs[] = { - { "nvidia_drv.", 11, /* strlen("nvidia_drv.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libvdpau_nvidia.", 16, /* strlen("libvdpau_nvidia.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-cfg.", 14, /* strlen("libnvidia-cfg.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libcuda.", 8, /* strlen("libcuda.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-compiler.", 19, /* strlen("libnvidia-compiler.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvcuvid.", 11, /* strlen("libnvcuvid.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-ml.", 13, /* strlen("libnvidia-ml.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-encode.", 17, /* strlen("libnvidia-encode.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-vgx.", 14, /* strlen("libnvidia-vgx.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-ifr.", 14, /* strlen("libnvidia-ifr.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-vgxcfg.", 17, /* strlen("libnvidia-vgxcfg.") */ - NULL, CONFLICT_ARCH_ALL }, - { NULL, 0, NULL, CONFLICT_ARCH_ALL } -}; - -static ConflictingFileInfo __xfree86_vdpau_wrapper_libs[] = { - { "libvdpau.", 9, /* strlen("libvdpau.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libvdpau_trace.", 15, /* strlen("libvdpau_trace.") */ - NULL, CONFLICT_ARCH_ALL }, - { NULL, 0, NULL, CONFLICT_ARCH_ALL } -}; - -/* - * find_conflicting_xfree86_libraries() - search for conflicting - * libraries under the XFree86 installation prefix, for all possible - * libdirs. - */ - -static void find_conflicting_xfree86_libraries(Options *op, - const char *xprefix, - FileList *l) -{ - if (!op->no_opengl_files) { - find_conflicting_libraries(op, xprefix, __xfree86_opengl_libs, l); - } - find_conflicting_libraries(op, xprefix, __xfree86_non_opengl_libs, l); - if (op->install_vdpau_wrapper == NV_OPTIONAL_BOOL_TRUE) { - find_conflicting_libraries(op, xprefix, __xfree86_vdpau_wrapper_libs, l); - } - -} /* find_conflicting_xfree86_libraries() */ - - - -/* - * find_conflicting_xfree86_libraries_fullpath() - same as - * find_conflicting_xfree86_libraries, but bypasses the - * find_conflicting_libraries step, which appends "lib", "lib64", and - * "lib32" to the path name. Use this when you have the fullpath that - * you want searched. - */ - -static void find_conflicting_xfree86_libraries_fullpath(Options *op, - char *path, - FileList *l) -{ - if (!op->no_opengl_files) { - find_conflicting_files(op, path, __xfree86_opengl_libs, l, NULL); - } - find_conflicting_files(op, path, __xfree86_non_opengl_libs, l, NULL); - if (op->install_vdpau_wrapper == NV_OPTIONAL_BOOL_TRUE) { - find_conflicting_files(op, path, __xfree86_vdpau_wrapper_libs, l, NULL); - } - -} /* find_conflicting_xfree86_libraries_fullpath() */ - - - -static ConflictingFileInfo __opengl_libs[] = { - { "libnvidia-glcore.", 17, /* strlen("libnvidia-glcore.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libGL.", 6, /* strlen("libGL.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-tls.", 14, /* strlen("libnvidia-tls.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libGLwrapper.", 13, /* strlen("libGLwrapper.") */ - NULL, CONFLICT_ARCH_ALL }, - { NULL, 0, NULL, CONFLICT_ARCH_ALL } -}; - -static ConflictingFileInfo __non_opengl_libs[] = { - { "libnvidia-cfg.", 14, /* strlen("libnvidia-cfg.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libcuda.", 8, /* strlen("libcuda.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-compiler.", 19, /* strlen("libnvidia-compiler.") */ - NULL, CONFLICT_ARCH_ALL }, - { "libnvidia-ml.", 13, /* strlen("libnvidia-ml.") */ - NULL, CONFLICT_ARCH_ALL }, - { NULL, 0, NULL, CONFLICT_ARCH_ALL } -}; - -/* - * find_conflicting_opengl_libraries() - search for conflicting - * libraries under the OpenGL installation prefix, for all possible - * libdirs. - */ - -static void find_conflicting_opengl_libraries(Options *op, - const char *glprefix, - FileList *l) -{ - if (!op->no_opengl_files) { - find_conflicting_libraries(op, glprefix, __opengl_libs, l); - } - find_conflicting_libraries(op, glprefix, __non_opengl_libs, l); - -} /* find_conflicting_opengl_libraries() */ - - /* * find_conflicting_kernel_modules() - search for conflicting kernel @@ -857,38 +708,7 @@ static int ignore_conflicting_file(Options *op, struct stat stat_buf; char *file = MAP_FAILED; int ret = FALSE; - int i, len; - - /* check if the file only conflicts on certain architectures */ - - if (info.conflictArch != CONFLICT_ARCH_ALL) { - ElfFileType elftype = get_elf_architecture(filename); - - switch (elftype) { - case ELF_ARCHITECTURE_32: - ret = info.conflictArch != CONFLICT_ARCH_32; - break; - case ELF_ARCHITECTURE_64: - ret = info.conflictArch != CONFLICT_ARCH_64; - break; - default: - /* - * XXX ignore symlinks with indeterminate architectures: their - * targets may have already been deleted, and they'll be reused - * or replaced as part of the installation, anyway. - */ - if (lstat(filename, &stat_buf) == -1) { - ui_warn(op, "Unable to stat '%s'.", filename); - } else if ((stat_buf.st_mode & S_IFLNK) == S_IFLNK) { - ret = TRUE; - } else { - ui_warn(op, "Unable to determine the architecture of the " - "file '%s', which has an architecture-specific " - "conflict.", filename); - } - break; - } - } + int i, len, size = 0; /* if no requiredString, do not check for the required string */ @@ -908,11 +728,13 @@ static int ignore_conflicting_file(Options *op, goto cleanup; } - if (!stat_buf.st_size) { + size = stat_buf.st_size; + + if (!size) { goto cleanup; } - if ((file = mmap(0, stat_buf.st_size, PROT_READ, + if ((file = mmap(0, size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0)) == MAP_FAILED) { ui_error(op, "Unable to map file '%s' for reading (%s)", filename, strerror(errno)); @@ -930,9 +752,9 @@ static int ignore_conflicting_file(Options *op, len = strlen(info.requiredString); - for (i = 0; (i + len) <= stat_buf.st_size; i++) { + for (i = 0; (i + len) <= size; i++) { if ((strncmp(&file[i], info.requiredString, len) == 0) && - (((i + len) == stat_buf.st_size) || (file[i+len] == '\0'))) { + (((i + len) == size) || (file[i+len] == '\0'))) { ret = FALSE; break; } @@ -943,7 +765,7 @@ static int ignore_conflicting_file(Options *op, cleanup: if (file != MAP_FAILED) { - munmap(file, stat_buf.st_size); + munmap(file, size); } if (fd != -1) { @@ -1027,65 +849,6 @@ static void find_conflicting_files(Options *op, - -/* - * find_conflicting_libraries() - search for any conflicting - * libraries in all relevant libdirs within the hierarchy under - * the given prefix. - */ - -static void find_conflicting_libraries(Options *op, - const char *prefix, - ConflictingFileInfo *files, - FileList *l) -{ - int i, j; - char *paths[4]; - - /* - * stop recursing into any "nvidia-cg-toolkit" - * directory to prevent libGL.so.1 from being deleted - * (see bug 843595). - */ - static const NoRecursionDirectory skipdirs[] = { - { -1, "nvidia-cg-toolkit" }, - { 0, NULL } - }; - - paths[0] = nvstrcat(prefix, "/", "lib", NULL); - paths[1] = nvstrcat(prefix, "/", "lib64", NULL); - paths[2] = nvstrcat(prefix, "/", "lib32", NULL); - paths[3] = NULL; - - for (i = 0; paths[i]; i++) { - for (j = 0; (j < 3) && paths[i]; j++) { - /* - * XXX Check if any one of the 'paths' entries really - * is a symbolic link pointing to one of the other - * entries. The logic could be made smarter, since it's - * unlikely that ../lib32 would be a symbolic link to - * ../lib64 or vice versa. - */ - if (!paths[j] || (i == j)) continue; - - if (is_symbolic_link_to(paths[i], paths[j])) { - ui_expert(op, "The conflicting library search path " - "'%s' is a symbolic link to the library " - "search path '%s'; skipping '%s'.", - paths[i], paths[j], paths[i]); - free(paths[i]); paths[i] = NULL; - } - } - - if (paths[i]) find_conflicting_files(op, paths[i], files, l, skipdirs); - } - - for (i = 0; i < 3; i++) - nvfree(paths[i]); - -} /* find_conflicting_libraries() */ - - /* * condense_file_list() - Take a FileList stucture and delete any * duplicate entries in the list. This is a pretty brain dead diff --git a/common-utils/common-utils.c b/common-utils/common-utils.c index f581f0d..81fd7ed 100644 --- a/common-utils/common-utils.c +++ b/common-utils/common-utils.c @@ -522,6 +522,68 @@ char *nv_basename(const char *path) } +/* + * nv_mkdir_recursive() - make a directory and all parent directories as needed. + * dir_list is an optional arguments that if not empty, will be set to a string + * containing a newline separated list of all directories created. + */ +int nv_mkdir_recursive(const char *path, const mode_t mode, + char **error_str, char **dir_list) +{ + char *c, *tmp, ch, *list; + int success = FALSE; + + if (!path || !path[0]) { + return FALSE; + } + + tmp = nvstrdup(path); + remove_trailing_slashes(tmp); + + list = NULL; + + c = tmp; + do { + c++; + if ((*c == '/') || (*c == '\0')) { + ch = *c; + *c = '\0'; + if (!directory_exists(tmp)) { + char *tmplist; + if (mkdir(tmp, mode) != 0) { + *error_str = + nvasprintf("Failure creating directory '%s' : (%s)", + tmp, strerror(errno)); + goto done; + } + /* Prepend the created directory path to a running list */ + if (dir_list) { + tmplist = list; + list = nvstrcat(tmp, "\n", tmplist, NULL); + free(tmplist); + } + } + *c = ch; + } + } while (*c); + + /* Log any created directories */ + if (dir_list && list) { + *dir_list = list; + } + + success = TRUE; + + done: + + if (!dir_list) { + free(list); + } + free(tmp); + return success; +} + + /****************************************************************************/ /* string helper functions */ /****************************************************************************/ @@ -611,3 +673,39 @@ char *nv_trim_char_strict(char *string, char trim) { return NULL; } +/* + * directory_exists() - test whether the given directory exists + */ + +int directory_exists(const char *dir) +{ + struct stat stat_buf; + + if ((stat (dir, &stat_buf) == -1) || (!S_ISDIR(stat_buf.st_mode))) { + return FALSE; + } else { + return TRUE; + } +} + +/* + * remove_trailing_slashes() - begin at the end of the given string, + * and overwrite slashes with NULL as long as we find slashes. + */ + +void remove_trailing_slashes(char *string) +{ + int len; + + if (string == NULL) { + return; + } + + len = strlen(string); + + while (string[len-1] == '/') { + string[--len] = '\0'; + } + +} + diff --git a/common-utils/common-utils.h b/common-utils/common-utils.h index 3db71b6..709ff02 100644 --- a/common-utils/common-utils.h +++ b/common-utils/common-utils.h @@ -62,10 +62,15 @@ int nv_get_file_length(const char *filename); void nv_set_file_length(const char *filename, int fd, int len); void *nv_mmap(const char *filename, size_t len, int prot, int flags, int fd); char *nv_basename(const char *path); +int nv_mkdir_recursive(const char *path, const mode_t mode, + char **error_str, char **log_str); char *nv_trim_space(char *string); char *nv_trim_char(char *string, char trim); char *nv_trim_char_strict(char *string, char trim); +void remove_trailing_slashes(char *string); + +int directory_exists(const char *dir); #if defined(__GNUC__) # define NV_INLINE __inline__ diff --git a/common-utils/nvgetopt.c b/common-utils/nvgetopt.c index 1c6c9b8..aaebd78 100644 --- a/common-utils/nvgetopt.c +++ b/common-utils/nvgetopt.c @@ -42,6 +42,7 @@ int nvgetopt(int argc, int ret = 0; int negate = NVGETOPT_FALSE; int disable = NVGETOPT_FALSE; + int double_dash = NVGETOPT_FALSE; const NVGetoptOption *o = NULL; static int argv_index = 0; @@ -65,6 +66,7 @@ int nvgetopt(int argc, if ((arg[0] == '-') && (arg[1] == '-')) { name = arg + 2; + double_dash = NVGETOPT_TRUE; } else if (arg[0] == '-') { name = arg + 1; } else { @@ -80,16 +82,26 @@ int nvgetopt(int argc, c = name; while (*c) { - if (*c == '=') { argument = c + 1; *c = '\0'; break; } + if (*c == '=') { + argument = c + 1; + *c = '\0'; + break; + } c++; } /* + * if there is no character after '--' then stop processing options. * if the string is terminated after one character, interpret it * as a short option. Otherwise, interpret it as a long option. */ - if (name[1] == '\0') { /* short option */ + if (name[0] == '\0') { + if (double_dash && argument == NULL) { /* option list terminator */ + ret = -1; + goto done; + } + } else if (name[1] == '\0') { /* short option */ for (i = 0; options[i].name; i++) { if (options[i].val == name[0]) { o = &options[i]; @@ -94,31 +94,41 @@ uint32 compute_crc_from_buffer(const uint8 *buf, int len) uint32 compute_crc(Options *op, const char *filename) { uint32 cword = ~0; - uint8 *buf; + uint8 *buf = MAP_FAILED; + int success = FALSE; int fd; struct stat stat_buf; - size_t len; + size_t len = 0; - if ((fd = open(filename, O_RDONLY)) == -1) goto fail; - if (fstat(fd, &stat_buf) == -1) goto fail; + if ((fd = open(filename, O_RDONLY)) == -1) goto done; + if (fstat(fd, &stat_buf) == -1) goto done; - if (stat_buf.st_size == 0) return 0; + if (stat_buf.st_size == 0) { + cword = 0; + success = TRUE; + goto done; + } len = stat_buf.st_size; buf = mmap(0, len, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0); - if (buf == (void *) -1) goto fail; + if (buf == MAP_FAILED) goto done; cword = compute_crc_from_buffer(buf, len); - if (munmap(buf, len) == -1) goto fail; - if (close(fd) == -1) goto fail; + success = TRUE; - return cword; + done: + if (!success) { + ui_warn(op, "Unable to compute CRC for file '%s' (%s).", + filename, strerror(errno)); + } - fail: - - ui_warn(op, "Unable to compute CRC for file '%s' (%s).", - filename, strerror(errno)); + if (buf != MAP_FAILED) { + munmap(buf, len); + } + if (fd >= 0) { + close(fd); + } return cword; diff --git a/dist-files.mk b/dist-files.mk index b08a951..c4b104f 100644 --- a/dist-files.mk +++ b/dist-files.mk @@ -73,11 +73,9 @@ DIST_FILES += rtld_test_Linux-x86_64 DIST_FILES += rtld_test_Linux-armv7l-gnueabi DIST_FILES += rtld_test_Linux-armv7l-gnueabihf -DIST_FILES += tls_test_Linux-ia64 DIST_FILES += tls_test_Linux-x86 DIST_FILES += tls_test_Linux-x86_64 -DIST_FILES += tls_test_dso_Linux-ia64.so DIST_FILES += tls_test_dso_Linux-x86.so DIST_FILES += tls_test_dso_Linux-x86_64.so @@ -57,8 +57,7 @@ int remove_directory(Options *op, const char *victim) struct stat stat_buf; DIR *dir; struct dirent *ent; - char *filename; - int len; + int success = TRUE; if (lstat(victim, &stat_buf) == -1) { ui_error(op, "failure to open '%s'", victim); @@ -75,7 +74,9 @@ int remove_directory(Options *op, const char *victim) return FALSE; } - while ((ent = readdir(dir)) != NULL) { + while (success && (ent = readdir(dir)) != NULL) { + char *filename; + int len; if (((strcmp(ent->d_name, ".")) == 0) || ((strcmp(ent->d_name, "..")) == 0)) continue; @@ -86,30 +87,32 @@ int remove_directory(Options *op, const char *victim) if (lstat(filename, &stat_buf) == -1) { ui_error(op, "failure to open '%s'", filename); - free(filename); - return FALSE; - } - - if (S_ISDIR(stat_buf.st_mode)) { - remove_directory(op, filename); + success = FALSE; } else { - if (unlink(filename) != 0) { - ui_error(op, "Failure removing file %s (%s)", - filename, strerror(errno)); + if (S_ISDIR(stat_buf.st_mode)) { + success = remove_directory(op, filename); + } else { + if (unlink(filename) != 0) { + ui_error(op, "Failure removing file %s (%s)", + filename, strerror(errno)); + success = FALSE; + } } } + free(filename); } + closedir(dir); + if (rmdir(victim) != 0) { ui_error(op, "Failure removing directory %s (%s)", victim, strerror(errno)); return FALSE; } - return TRUE; - -} /* remove_directory() */ + return success; +} @@ -125,7 +128,7 @@ int touch_directory(Options *op, const char *victim) DIR *dir; struct dirent *ent; struct utimbuf time_buf; - char *filename; + int success = FALSE; if (lstat(victim, &stat_buf) == -1) { ui_error(op, "failure to open '%s'", victim); @@ -150,6 +153,8 @@ int touch_directory(Options *op, const char *victim) /* loop over each entry in the directory */ while ((ent = readdir(dir)) != NULL) { + char *filename; + int entry_failed = FALSE; if (((strcmp(ent->d_name, ".")) == 0) || ((strcmp(ent->d_name, "..")) == 0)) continue; @@ -160,16 +165,16 @@ int touch_directory(Options *op, const char *victim) if (lstat(filename, &stat_buf) == -1) { ui_error(op, "failure to open '%s'", filename); - nvfree(filename); - return FALSE; + entry_failed = TRUE; + goto entry_done; } /* if it is a directory, call this recursively */ if (S_ISDIR(stat_buf.st_mode)) { if (!touch_directory(op, filename)) { - nvfree(filename); - return FALSE; + entry_failed = TRUE; + goto entry_done; } } @@ -177,21 +182,28 @@ int touch_directory(Options *op, const char *victim) if (utime(filename, &time_buf) != 0) { ui_error(op, "Error setting modification time for %s", filename); - nvfree(filename); - return FALSE; + entry_failed = TRUE; + goto entry_done; } + entry_done: nvfree(filename); + if (entry_failed) { + goto done; + } } + success = TRUE; + + done: + if (closedir(dir) != 0) { ui_error(op, "Error while closing directory %s.", victim); - return FALSE; + success = FALSE; } - - return TRUE; -} /* touch_directory() */ + return success; +} /* @@ -205,48 +217,51 @@ int touch_directory(Options *op, const char *victim) int copy_file(Options *op, const char *srcfile, const char *dstfile, mode_t mode) { - int src_fd, dst_fd; + int src_fd = -1, dst_fd = -1; + int success = FALSE; struct stat stat_buf; char *src, *dst; if ((src_fd = open(srcfile, O_RDONLY)) == -1) { ui_error (op, "Unable to open '%s' for copying (%s)", srcfile, strerror (errno)); - goto fail; + goto done; } if ((dst_fd = open(dstfile, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1) { ui_error (op, "Unable to create '%s' for copying (%s)", dstfile, strerror (errno)); - goto fail; + goto done; } if (fstat(src_fd, &stat_buf) == -1) { ui_error (op, "Unable to determine size of '%s' (%s)", srcfile, strerror (errno)); - goto fail; + goto done; } - if (stat_buf.st_size == 0) + if (stat_buf.st_size == 0) { + success = TRUE; goto done; + } if (lseek(dst_fd, stat_buf.st_size - 1, SEEK_SET) == -1) { ui_error (op, "Unable to set file size for '%s' (%s)", dstfile, strerror (errno)); - goto fail; + goto done; } if (write(dst_fd, "", 1) != 1) { ui_error (op, "Unable to write file size for '%s' (%s)", dstfile, strerror (errno)); - goto fail; + goto done; } if ((src = mmap(0, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_SHARED, src_fd, 0)) == (void *) -1) { ui_error (op, "Unable to map source file '%s' for copying (%s)", srcfile, strerror (errno)); - goto fail; + goto done; } if ((dst = mmap(0, stat_buf.st_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, dst_fd, 0)) == (void *) -1) { ui_error (op, "Unable to map destination file '%s' for copying (%s)", dstfile, strerror (errno)); - goto fail; + goto done; } memcpy (dst, src, stat_buf.st_size); @@ -254,31 +269,36 @@ int copy_file(Options *op, const char *srcfile, if (munmap (src, stat_buf.st_size) == -1) { ui_error (op, "Unable to unmap source file '%s' after copying (%s)", srcfile, strerror (errno)); - goto fail; + goto done; } if (munmap (dst, stat_buf.st_size) == -1) { ui_error (op, "Unable to unmap destination file '%s' after " "copying (%s)", dstfile, strerror (errno)); - goto fail; + goto done; } + success = TRUE; + done: - /* - * the mode used to create dst_fd may have been affected by the - * user's umask; so explicitly set the mode again - */ - fchmod(dst_fd, mode); + if (success) { + /* + * the mode used to create dst_fd may have been affected by the + * user's umask; so explicitly set the mode again + */ - close (src_fd); - close (dst_fd); - - return TRUE; + fchmod(dst_fd, mode); + } - fail: - return FALSE; + if (src_fd != -1) { + close (src_fd); + } + if (dst_fd != -1) { + close (dst_fd); + } -} /* copy_file() */ + return success; +} @@ -368,7 +388,7 @@ char *write_temp_file(Options *op, const int len, if (ret) { return tmpfile; } else { - if (tmpfile) nvfree(tmpfile); + nvfree(tmpfile); return NULL; } @@ -385,6 +405,7 @@ char *write_temp_file(Options *op, const int len, void select_tls_class(Options *op, Package *p) { +#if defined(NV_TLS_TEST) int i; if (!tls_test(op, FALSE)) { @@ -456,7 +477,7 @@ void select_tls_class(Options *op, Package *p) } #endif /* NV_X86_64 */ - +#endif /* NV_TLS_TEST */ } /* select_tls_class() */ @@ -534,6 +555,10 @@ int set_destinations(Options *op, Package *p) case FILE_TYPE_CUDA_LIB: case FILE_TYPE_CUDA_SYMLINK: + case FILE_TYPE_OPENCL_LIB: + case FILE_TYPE_OPENCL_WRAPPER_LIB: + case FILE_TYPE_OPENCL_LIB_SYMLINK: + case FILE_TYPE_OPENCL_WRAPPER_SYMLINK: if (p->entries[i].compat_arch == FILE_COMPAT_ARCH_COMPAT32) { prefix = op->compat32_prefix; dir = op->compat32_libdir; @@ -550,13 +575,6 @@ int set_destinations(Options *op, Package *p) path = ""; break; - case FILE_TYPE_XLIB_SHARED_LIB: - case FILE_TYPE_XLIB_STATIC_LIB: - case FILE_TYPE_XLIB_SYMLINK: - prefix = op->x_library_path; - dir = path = ""; - break; - case FILE_TYPE_XMODULE_SHARED_LIB: case FILE_TYPE_GLX_MODULE_SHARED_LIB: case FILE_TYPE_XMODULE_SYMLINK: @@ -714,6 +732,11 @@ int set_destinations(Options *op, Package *p) path = ""; break; + case FILE_TYPE_XORG_OUTPUTCLASS_CONFIG: + prefix = op->x_sysconfig_path; + dir = path = ""; + break; + default: /* @@ -768,8 +791,8 @@ int set_destinations(Options *op, Package *p) int get_license_acceptance(Options *op) { struct stat buf; - char *text, *tmp; - int fd; + char *text = MAP_FAILED, *tmp = NULL; + int fd = -1, accepted = FALSE, size = 0; /* trivial accept if the user accepted on the command line */ @@ -778,46 +801,50 @@ int get_license_acceptance(Options *op) return TRUE; } - if ((fd = open(LICENSE_FILE, 0x0)) == -1) goto failed; + if ((fd = open(LICENSE_FILE, 0x0)) == -1) goto done; - if (fstat(fd, &buf) != 0) goto failed; + if (fstat(fd, &buf) != 0) goto done; + + size = buf.st_size; - if ((text = (char *) mmap(NULL, buf.st_size, PROT_READ, + if ((text = (char *) mmap(NULL, size, PROT_READ, MAP_FILE|MAP_SHARED, - fd, 0x0)) == (char *) -1) goto failed; + fd, 0x0)) == MAP_FAILED) goto done; /* * the mmap'ed license file may not be NULL terminated, so copy it * into a temporary buffer and explicity NULL terminate the string */ - tmp = nvalloc(buf.st_size + 1); - memcpy(tmp, text, buf.st_size); - tmp[buf.st_size] = '\0'; + tmp = nvalloc(size + 1); + memcpy(tmp, text, size); + tmp[size] = '\0'; if (!ui_display_license(op, tmp)) { ui_message(op, "License not accepted. Aborting installation."); - nvfree(tmp); - munmap(text, buf.st_size); - close(fd); - return FALSE; + } else { + ui_log(op, "License accepted."); + accepted = TRUE; } - ui_log(op, "License accepted."); - + done: + nvfree(tmp); - munmap(text, buf.st_size); - close(fd); - - return TRUE; - failed: - - ui_error(op, "Unable to open License file '%s' (%s)", - LICENSE_FILE, strerror(errno)); - return FALSE; + if (text == MAP_FAILED || fd == -1) { + ui_error(op, "Unable to open License file '%s' (%s)", + LICENSE_FILE, strerror(errno)); + } + + if (text != MAP_FAILED) { + munmap(text, size); + } + if (fd != -1) { + close(fd); + } -} /* get_license_acceptance() */ + return accepted; +} @@ -850,8 +877,9 @@ int get_prefixes (Options *op) * after the default prefixes/paths are assigned. */ - get_x_library_and_module_paths(op); - + if (op->x_files_packaged) { + get_x_library_and_module_paths(op); + } if (op->expert) { ret = ui_get_input(op, op->x_library_path, @@ -1106,23 +1134,6 @@ void remove_opengl_files_from_package(Options *op, Package *p) } -/* - * remove_trailing_slashes() - begin at the end of the given string, - * and overwrite slashes with NULL as long as we find slashes. - */ - -void remove_trailing_slashes(char *s) -{ - int len; - - if (s == NULL) return; - len = strlen(s); - - while (s[len-1] == '/') s[--len] = '\0'; - -} /* remove_trailing_slashes() */ - - /* * mode_string_to_mode() - convert the string s @@ -1179,23 +1190,6 @@ char *mode_to_permission_string(mode_t mode) /* - * directory_exists() - - */ - -int directory_exists(Options *op, const char *dir) -{ - struct stat stat_buf; - - if ((stat (dir, &stat_buf) == -1) || (!S_ISDIR(stat_buf.st_mode))) { - return FALSE; - } else { - return TRUE; - } -} /* directory_exists() */ - - - -/* * confirm_path() - check that the path exists; if not, ask the user * if it's OK to create it and then do mkdir(). * @@ -1215,7 +1209,7 @@ int confirm_path(Options *op, const char *path) /* return TRUE if the path already exists and is a directory */ - if (directory_exists(op, path)) return TRUE; + if (directory_exists(path)) return TRUE; if (ui_multiple_choice(op, choices, 2, 0, "The directory '%s' does not " "exist; would you like to create it, or would you " @@ -1244,46 +1238,23 @@ int confirm_path(Options *op, const char *path) int mkdir_recursive(Options *op, const char *path, const mode_t mode, int log) { - char *c, *tmp, ch, *list, *tmplist; - - if (!path || !path[0]) return FALSE; - - tmp = nvstrdup(path); - remove_trailing_slashes(tmp); - - list = NULL; + char *error_str = NULL; + char *log_str = NULL; + int success = FALSE; - c = tmp; - do { - c++; - if ((*c == '/') || (*c == '\0')) { - ch = *c; - *c = '\0'; - if (!directory_exists(op, tmp)) { - if (mkdir(tmp, mode) != 0) { - ui_error(op, "Failure creating directory '%s': (%s)", - tmp, strerror(errno)); - free(tmp); - return FALSE; - } - /* Prepend the created directory path to a running list */ - tmplist = list; - list = nvstrcat(tmp, "\n", tmplist, NULL); - free(tmplist); - } - *c = ch; - } - } while (*c); + success = nv_mkdir_recursive(path, mode, &error_str, log ? &log_str : NULL); - /* Log any created directories */ - if (log && list) { - log_mkdir(op, list); + if (log_str) { + log_mkdir(op, log_str); + free(log_str); } - free(list); - free(tmp); - return TRUE; + if (error_str) { + ui_error(op, "%s", error_str); + free(error_str); + } + return success; } @@ -1481,7 +1452,7 @@ char *get_tmpdir(Options *op) tmpdirs[3] = getenv("HOME"); for (i = 0; i < 4; i++) { - if (tmpdirs[i] && directory_exists(op, tmpdirs[i])) { + if (tmpdirs[i] && directory_exists(tmpdirs[i])) { return (tmpdirs[i]); } } @@ -1505,7 +1476,7 @@ char *make_tmpdir(Options *op) tmpdir = nvstrcat(op->tmpdir, "/nvidia-", tmp, NULL); - if (directory_exists(op, tmpdir)) { + if (directory_exists(tmpdir)) { remove_directory(op, tmpdir); } @@ -1629,8 +1600,7 @@ int copy_directory_contents(Options *op, const char *src, const char *dst) { DIR *dir; struct dirent *ent; - char *srcfile, *dstfile; - struct stat stat_buf; + int status = FALSE; if ((dir = opendir(src)) == NULL) { ui_error(op, "Unable to open directory '%s' (%s).", @@ -1639,6 +1609,9 @@ int copy_directory_contents(Options *op, const char *src, const char *dst) } while ((ent = readdir(dir)) != NULL) { + struct stat stat_buf; + char *srcfile, *dstfile; + int ret; if (((strcmp(ent->d_name, ".")) == 0) || ((strcmp(ent->d_name, "..")) == 0)) continue; @@ -1654,12 +1627,20 @@ int copy_directory_contents(Options *op, const char *src, const char *dst) dstfile = nvstrcat(dst, "/", ent->d_name, NULL); - if (!copy_file(op, srcfile, dstfile, stat_buf.st_mode)) return FALSE; + ret = copy_file(op, srcfile, dstfile, stat_buf.st_mode); nvfree(srcfile); nvfree(dstfile); + + if (!ret) { + goto done; + } } + status = TRUE; + + done: + if (closedir(dir) != 0) { ui_error(op, "Failure while closing directory '%s' (%s).", src, strerror(errno)); @@ -1667,7 +1648,7 @@ int copy_directory_contents(Options *op, const char *src, const char *dst) return FALSE; } - return TRUE; + return status; } /* copy_directory_contents() */ @@ -1692,24 +1673,32 @@ int pack_precompiled_files(Options *op, Package *p, int num_files, /* make sure the precompiled_kernel_interface_directory exists */ - mkdir_recursive(op, p->precompiled_kernel_interface_directory, 0755, FALSE); + if (!mkdir_recursive(op, p->precompiled_kernel_interface_directory, 0755, + FALSE)) { + ui_error(op, "Failed to create the directory '%s'!", + p->precompiled_kernel_interface_directory); + return FALSE; + } /* use the time in the output string... should be fairly unique */ t = time(NULL); snprintf(time_str, 256, "%lu", t); - - /* read the proc version string */ - - proc_version_string = read_proc_version(op, op->proc_mount_point); /* use the uname string as the description */ - uname(&buf); + if (uname(&buf) != 0) { + ui_error(op, "Failed to retrieve uname identifiers from the kernel!"); + return FALSE; + } descr = nvstrcat(buf.sysname, " ", buf.release, " ", buf.version, " ", buf.machine, NULL); + + /* read the proc version string */ + + proc_version_string = read_proc_version(op, op->proc_mount_point); /* build the PrecompiledInfo struct */ @@ -1729,7 +1718,7 @@ int pack_precompiled_files(Options *op, Package *p, int num_files, nvfree(outfile); free_precompiled(info); - + if (ret) { return TRUE; } @@ -1738,7 +1727,6 @@ int pack_precompiled_files(Options *op, Package *p, int num_files, ui_error(op, "Unable to package precompiled kernel interface."); return FALSE; } - } @@ -2129,12 +2117,139 @@ int set_security_context(Options *op, const char *filename) ret = run_command(op, cmd, NULL, FALSE, 0, TRUE); ret = ((ret == 0) ? TRUE : FALSE); - if (cmd) nvfree(cmd); + nvfree(cmd); return ret; } /* set_security_context() */ +static char * const native_libdirs[] = { +#if defined(NV_X86_64) + DEFAULT_AMD64_TRIPLET_LIBDIR, +#elif defined(NV_X86) + DEFAULT_IA32_TRIPLET_LIBDIR, +#elif defined(NV_ARMV7) +#if defined(NV_GNUEABIHF) + DEFAULT_ARMV7HF_TRIPLET_LIBDIR, +#else + DEFAULT_ARMV7_TRIPLET_LIBDIR, +#endif /* GNUEABIHF */ +#elif defined(NV_AARCH64) + DEFAULT_AARCH64_TRIPLET_LIBDIR, +#elif defined(NV_PPC64LE) + DEFAULT_PPC64LE_TRIPLET_LIBDIR, +#endif +#if NV_ARCH_BITS == 32 + DEFAULT_32BIT_LIBDIR, +#elif NV_ARCH_BITS == 64 + DEFAULT_64BIT_LIBDIR, +#else +#error Unknown architecture! Please update utils.mk to add support for this \ +TARGET_ARCH, and make sure that an architecture-specific NV_$ARCH macro gets \ +defined, and that NV_ARCH_BITS gets defined to the correct word size in bits. +#endif + DEFAULT_LIBDIR, + NULL +}; + + +#if defined(NV_X86_64) +static char * const compat_libdirs[] = { + DEFAULT_IA32_TRIPLET_LIBDIR, + DEFAULT_32BIT_LIBDIR, + DEFAULT_LIBDIR, + NULL +}; +#endif + + + +/* + * get_ldconfig_cache() - retrieve the ldconfig(8) cache, or NULL on error + */ + +static char *get_ldconfig_cache(Options *op) +{ + char *data, *cmd; + int ret; + + cmd = nvstrcat(op->utils[LDCONFIG], " -p", NULL); + ret = run_command(op, cmd, &data, FALSE, 0, FALSE); + nvfree(cmd); + + if (ret != 0) { + nvfree(data); + return NULL; + } + + return data; +} + + +/* + * find_libdir() - search in 'prefix' (optionally under 'chroot'/'prefix') + * for directories in 'list', either in the ldconfig(8) cache or on the + * filesystem. return the first directory found, or NULL if none found. + */ + +static char *find_libdir(char * const * list, const char *prefix, + const char *ldconfig_cache, const char *chroot) +{ + int i; + char *path = NULL; + + for (i = 0; list[i]; i++) { + nvfree(path); + + path = nvstrcat(chroot ? chroot : "", + "/", prefix, "/", list[i], "/", NULL); + collapse_multiple_slashes(path); + + if (ldconfig_cache) { + if (strstr(ldconfig_cache, path)) { + break; + } + } else { + if (directory_exists(path)) { + break; + } + } + } + + nvfree(path); + return list[i]; +} + + +/* + * find_libdir_and_fall_back() - search for the first available directory from + * 'list' under 'prefix' that appears in the 'ldconfig_cache'. If no directory + * is found in 'ldconfig_cache', test for directory existence; if no directory + * from 'list' exists under 'prefix', default to DEFAULT_LIBDIR and print a + * warning message. + */ +static char * find_libdir_and_fall_back(Options *op, char * const * list, + const char *prefix, + const char *ldconfig_cache, + const char *name) +{ + char *libdir = find_libdir(list, prefix, ldconfig_cache, NULL); + if (!libdir) { + libdir = find_libdir(list, prefix, NULL, NULL); + } + if (!libdir) { + libdir = DEFAULT_LIBDIR; + ui_warn(op, "Unable to determine the default %s path. The path %s/%s " + "will be used, but this path was not detected in the " + "ldconfig(8) cache, and no directory exists at this path, " + "so it is likely that libraries installed there will not " + "be found by the loader.", name, prefix, libdir); + } + + return libdir; +} + + /* * get_default_prefixes_and_paths() - assign the default prefixes and * paths depending on the architecture, distribution and the X.Org @@ -2143,22 +2258,18 @@ int set_security_context(Options *op, const char *filename) void get_default_prefixes_and_paths(Options *op) { - char *default_libdir; - -#if defined(NV_X86_64) - if ((op->distro == DEBIAN) || - (op->distro == UBUNTU) || - (op->distro == ARCH)) { - default_libdir = DEBIAN_DEFAULT_64BIT_LIBDIR; - } else { - default_libdir = DEFAULT_64BIT_LIBDIR; - } -#else - default_libdir = DEFAULT_LIBDIR; -#endif + char *default_libdir, *ldconfig_cache; if (!op->opengl_prefix) op->opengl_prefix = DEFAULT_OPENGL_PREFIX; + + ldconfig_cache = get_ldconfig_cache(op); + + default_libdir = find_libdir_and_fall_back(op, native_libdirs, + op->opengl_prefix, + ldconfig_cache, "library"); + + if (!op->opengl_libdir) op->opengl_libdir = default_libdir; if (!op->opengl_incdir) @@ -2171,8 +2282,20 @@ void get_default_prefixes_and_paths(Options *op) op->x_prefix = DEFAULT_X_PREFIX; } } - if (!op->x_libdir) - op->x_libdir = default_libdir; + if (!op->x_libdir) { + /* XXX if we just inherit default_libdir from above, we could end up + * with e.g. /usr/lib/x86_64-linux-gnu/xorg/modules as the module path. + * In practice, we haven't seen the tuplet-based paths used for X + * module paths, so skip the first (tuplet-based) entry from + * native_libdirs when getting a default value for x_libdir. This is + * only used when we have to guess the paths when the query fails. */ + op->x_libdir = find_libdir_and_fall_back(op, &native_libdirs[1], + op->x_prefix, ldconfig_cache, + "X library"); + } + + nvfree(ldconfig_cache); + if (!op->x_moddir) { if (op->modular_xorg) { op->x_moddir = XORG7_DEFAULT_X_MODULEDIR ; @@ -2184,58 +2307,6 @@ void get_default_prefixes_and_paths(Options *op) #if defined(NV_X86_64) if (!op->compat32_prefix) op->compat32_prefix = DEFAULT_OPENGL_PREFIX; - - if (!op->compat32_libdir) { - if ((op->distro == UBUNTU) || - (op->distro == GENTOO) || - (op->distro == ARCH)) { - op->compat32_libdir = UBUNTU_DEFAULT_COMPAT32_LIBDIR; - } else { - op->compat32_libdir = DEFAULT_LIBDIR; - } - } - - if (op->distro == DEBIAN && !op->compat32_chroot) { - /* - * 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 *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) { - /* - * Paths don't exist or are symbolic links. Use the compat32 - * chroot path instead. - */ - - op->compat32_chroot = DEBIAN_DEFAULT_COMPAT32_CHROOT; - } - - } - #endif if (!op->utility_prefix) @@ -2268,6 +2339,119 @@ void get_default_prefixes_and_paths(Options *op) } /* get_default_prefixes_and_paths() */ +#if defined NV_X86_64 +/* + * compat32_conflict() - given a value for the compatibility library directory, + * determines whether a conflict exists between the proposed compatibility + * library path and the existing OpenGL library path. e.g. if the native path + * is /usr/lib/x86_64-linux-gnu, then /usr/lib is probably not a good path for + * compat32 libs. On the other hand, /usr/lib/i386-linux-gnu might be a valid + * compat32 directory for a system where /usr/lib is the native library + * directory, so the comparison is one-directional. + * + * XXX this assumes that the native directory would never be a subdirectory of + * the compat directory, which might not actually be true. + */ +static int compat32_conflict(Options *op, const char *compat_libdir) +{ + char *native_path, *compat_path; + int ret, is_subdir; + + native_path = nvstrcat(op->opengl_prefix, "/", op->opengl_libdir, NULL); + compat_path = nvstrcat(op->compat32_chroot ? op->compat32_chroot : "", + "/", op->compat32_prefix, "/", compat_libdir, NULL); + + ret = is_subdirectory(compat_path, native_path, &is_subdir); + + if (!ret) { + ui_error(op, "Failed to determine whether '%s' is a subdirectory of " + "'%s'; '%s' will not be considered as a candidate location " + "for installing 32-bit compatibility libraries.", + native_path, compat_path, compat_path); + is_subdir = TRUE; + } + + nvfree(native_path); + nvfree(compat_path); + + return is_subdir; +} +#endif + + +/* + * get_compat32_path() - detect the appropriate path for installing the 32-bit + * compatibility files. This function must be called after parse_manifest(), + * and before set_destinations(). + */ +void get_compat32_path(Options *op) +{ +#if defined(NV_X86_64) + char *ldconfig_cache = get_ldconfig_cache(op); + + if (!op->compat32_prefix) + op->compat32_prefix = DEFAULT_OPENGL_PREFIX; + + if(!op->compat32_libdir) { + char *compat_libdir; + + + /* First, search the ldconfig(8) cache and filesystem normally */ + compat_libdir = find_libdir(compat_libdirs, op->compat32_prefix, + ldconfig_cache, op->compat32_chroot); + + if (!compat_libdir || compat32_conflict(op, compat_libdir)) { + compat_libdir = find_libdir(compat_libdirs, op->compat32_prefix, + NULL, op->compat32_chroot); + } + + /* + * If we still didn't find a suitable directory, and the user did not + * specify an explicit chroot, try the old Debian 32-bit chroot. + */ + if ((!compat_libdir || compat32_conflict(op, compat_libdir)) && + !op->compat32_chroot) { + op->compat32_chroot = DEBIAN_DEFAULT_COMPAT32_CHROOT; + + compat_libdir = find_libdir(compat_libdirs, op->compat32_prefix, + ldconfig_cache, op->compat32_chroot); + + if (!compat_libdir || compat32_conflict(op, compat_libdir)) { + compat_libdir = find_libdir(compat_libdirs, op->compat32_prefix, + NULL, op->compat32_chroot); + } + + /* + * If we still didn't find a suitable path in the old Debian chroot, + * reset the chroot path and the detected directory. + */ + if (!compat_libdir || compat32_conflict(op, compat_libdir)) { + op->compat32_chroot = NULL; + compat_libdir = NULL; + } + } + + /* If we still failed to find a directory, don't install 32-bit files */ + if (op->install_compat32_libs != NV_OPTIONAL_BOOL_FALSE && + (!compat_libdir || compat32_conflict(op, compat_libdir))) { + ui_warn(op, "Unable to find a suitable destination to install " + "32-bit compatibility libraries. Your system may not " + "be set up for 32-bit compatibility. 32-bit " + "compatibility files will not be installed; if you " + "wish to install them, re-run the installation and set " + "a valid directory with the --compat32-libdir option."); + op->install_compat32_libs = NV_OPTIONAL_BOOL_FALSE; + } + + if (op->install_compat32_libs != NV_OPTIONAL_BOOL_FALSE) { + op->compat32_libdir = compat_libdir; + } + } + + nvfree(ldconfig_cache); +#endif +} + /* * get_xdg_data_dir() - determine if the XDG_DATA_DIRS environment * variable is set; if set and not empty, return the first path @@ -2347,19 +2531,25 @@ static char *extract_x_path(char *str, char **next) } /* extract_x_path() */ +enum XPathType { + XPathLibrary, + XPathModule, + XPathSysConfig +}; /* * get_x_paths_helper() - helper function for determining the X - * library and module paths; returns 'TRUE' if we had to guess at the - * path + * library, module, and system xorg.conf.d paths; returns 'TRUE' if we had to + * guess at the path */ static int get_x_paths_helper(Options *op, - int library, + enum XPathType pathType, char *xserver_cmd, char *pkg_config_cmd, char *name, - char **path) + char **path, + int require_existing_directory) { char *dirs, *cmd, *dir, *next; int ret, guessed = 0; @@ -2381,7 +2571,7 @@ static int get_x_paths_helper(Options *op, * first, try the X server commandline option; this is the * recommended query mechanism as of X.Org 7.2 */ - if (op->utils[XSERVER]) { + if (op->utils[XSERVER] && xserver_cmd) { dirs = NULL; cmd = nvstrcat(op->utils[XSERVER], " ", xserver_cmd, NULL); @@ -2396,8 +2586,8 @@ static int get_x_paths_helper(Options *op, while (dir) { - if (directory_exists(op, dir)) { - + if (!require_existing_directory || directory_exists(dir)) { + ui_expert(op, "X %s path '%s' determined from `%s %s`", name, dir, op->utils[XSERVER], xserver_cmd); @@ -2443,7 +2633,7 @@ static int get_x_paths_helper(Options *op, while (dir) { - if (directory_exists(op, dir)) { + if (!require_existing_directory || directory_exists(dir)) { ui_expert(op, "X %s path '%s' determined from `%s %s`", name, dir, op->utils[PKG_CONFIG], @@ -2483,11 +2673,19 @@ static int get_x_paths_helper(Options *op, /* build the path */ - - if (library) { - *path = nvstrcat(op->x_prefix, "/", op->x_libdir, NULL); - } else { - *path = nvstrcat(op->x_library_path, "/", op->x_moddir, NULL); + + switch (pathType) { + case XPathLibrary: + *path = nvstrcat(op->x_prefix, "/", op->x_libdir, NULL); + break; + + case XPathModule: + *path = nvstrcat(op->x_library_path, "/", op->x_moddir, NULL); + break; + + case XPathSysConfig: + *path = nvstrcat(DEFAULT_X_DATAROOT_PATH, "/", DEFAULT_CONFDIR, NULL); + break; } remove_trailing_slashes(*path); @@ -2512,19 +2710,35 @@ static void get_x_library_and_module_paths(Options *op) */ guessed |= get_x_paths_helper(op, - TRUE, + XPathLibrary, "-showDefaultLibPath", "--variable=libdir xorg-server", "library", - &op->x_library_path); + &op->x_library_path, + TRUE); guessed |= get_x_paths_helper(op, - FALSE, + XPathModule, "-showDefaultModulePath", "--variable=moduledir xorg-server", "module", - &op->x_module_path); - + &op->x_module_path, + TRUE); + + /* + * Get the sysconfig path (typically /usr/share/X11/xorg.conf.d). This is + * only needed if the nvidia.conf OutputClass config snippet is going to be + * installed. Don't complain if we had to guess the path; the server will + * still work without it if xorg.conf is set up. + */ + get_x_paths_helper(op, + XPathSysConfig, + NULL, + "--variable=sysconfigdir xorg-server", + "sysconfig", + &op->x_sysconfig_path, + FALSE); + /* * done assigning op->x_library_path and op->x_module_path; if we * had to guess at either of the paths, print a warning @@ -2551,31 +2765,33 @@ static void get_x_library_and_module_paths(Options *op) */ char *get_filename(Options *op, const char *def, const char *msg) { - struct stat stat_buf; - char *file = NULL; + char *oldfile = nvstrdup(def); /* XXX This function should never be called if op->no_questions is set, * but just in case that happens by accident, do something besides looping * infinitely if def is a filename that doesn't exist. */ if (op->no_questions) { - return nvstrdup(def); + return oldfile; } - file = ui_get_input(op, file ? file : def, "%s", msg); + while (TRUE) { + struct stat stat_buf; + char *file = ui_get_input(op, oldfile, "%s", msg); + + nvfree(oldfile); - while (stat(file, &stat_buf) == -1 || - !(S_ISREG(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode))) { - char *oldfile = file; + if (file && stat(file, &stat_buf) != -1 && + (S_ISREG(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode))) { + return file; + } ui_message(op, "File \"%s\" does not exist, or is not a regular " - "file. Please enter another filename.", file); + "file. Please enter another filename.", file ? + file : "(null)"); - file = ui_get_input(op, oldfile ? oldfile : def, "%s", msg); - nvfree(oldfile); + oldfile = file; } - - return file; -} /* get_filename() */ +} @@ -2624,3 +2840,148 @@ void invalidate_package_entry(PackageEntry *entry) entry->dst = NULL; memset(&(entry->caps), 0, sizeof(entry->caps)); } + + +/* + * is_subdirectory() - test whether subdir is a subdir of dir + * returns TRUE on successful test, or FALSE on error + * sets *is_subdir based on the result of a successful test + * + * The testing is performed two ways: first, walk from subdir up to "/" + * and check at each step along the way if subdir's device and inode + * match dir's. If a match is not found this way, simply compare dir + * and subdir as normalized strings, up to the length of subdir, since + * the first method will fail if subdir is a symlink located inside dir + * whose target is outside of dir. + */ + +int is_subdirectory(const char *dir, const char *subdir, int *is_subdir) +{ + struct stat root_st, dir_st; + + if (stat("/", &root_st) != 0 || stat(dir, &dir_st) != 0) { + return FALSE; + } else { + struct stat testdir_st; + char *testdir = nvstrdup(subdir); + + *is_subdir = FALSE; + + do { + char *oldtestdir; + + if (stat(testdir, &testdir_st) != 0) { + nvfree(testdir); + return FALSE; + } + + if (testdir_st.st_dev == dir_st.st_dev && + testdir_st.st_ino == dir_st.st_ino) { + *is_subdir = TRUE; + break; + } + + oldtestdir = testdir; + testdir = nvstrcat(oldtestdir, "/..", NULL); + nvfree(oldtestdir); + } while (testdir_st.st_dev != root_st.st_dev || + testdir_st.st_ino != root_st.st_ino); + + nvfree(testdir); + } + + if (!*is_subdir) { + char *dir_with_slash, *subdir_with_slash; + + dir_with_slash = nvstrcat(dir, "/", NULL); + collapse_multiple_slashes(dir_with_slash); + subdir_with_slash = nvstrcat(subdir, "/", NULL); + collapse_multiple_slashes(subdir_with_slash); + + *is_subdir = (strncmp(dir_with_slash, subdir_with_slash, + strlen(dir_with_slash)) == 0); + + nvfree(dir_with_slash); + nvfree(subdir_with_slash); + } + + return TRUE; +} + +/* + * directory_equals() - if a is a subdirectory of b, and b is a subdirectory + * of a, then a and b are the same directory. Uses is_subdirectory() to do the + * subdirectory check, since the inode-based comparison will be resilient + * against symbolic links in either direction. + */ +static int directory_equals(const char *a, const char *b) +{ + int a_b, b_a; + + if (is_subdirectory(a, b, &a_b) && is_subdirectory(b, a, &b_a)) { + return a_b && b_a; + } + + return FALSE; +} + +/* + * get_opengl_libdir() - get the path where OpenGL libraries will be installed. + */ +static char *get_opengl_libdir(const Options *op) +{ + return nvstrcat(op->opengl_prefix, "/", op->opengl_libdir, "/", NULL); +} + +/* + * get_compat32_libdir() - get the path where 32-bit compatibility libraries + * will be installed, where applicable, or NULL when not applicable. + */ +static char *get_compat32_libdir(const Options *op) +{ +#if defined NV_X86_64 + return nvstrcat(op->compat32_chroot ? op->compat32_chroot : "", "/", + op->compat32_prefix, "/", op->compat32_libdir, "/", NULL); +#else + return NULL; +#endif +} + +/* + * add_libgl_abi_symlink() - check to see if either native or compatibility + * OpenGL libraries are destined to be installed to /usr/lib. If not, then + * create a symlink /usr/lib/libGL.so.1 that points to the native libGL.so.1, + * for compliance with the OpenGL ABI. Note: this function must be called + * after set_destinations() to avoid the hardcoded "/usr/lib" destination from + * being overwritten. + */ +void add_libgl_abi_symlink(Options *op, Package *p) +{ + static const char *usrlib = "/usr/lib/"; + char *libgl = nvstrdup("libGL.so.1"); + char *opengl_path = get_opengl_libdir(op); + char *opengl32_path = get_compat32_libdir(op); + + if (!directory_equals(usrlib, opengl_path) +#if defined (NV_X86_64) + && !directory_equals(usrlib, opengl32_path) +#endif + ) { + char *target = nvstrcat(opengl_path, "libGL.so.1", NULL); + add_package_entry(p, + libgl, + NULL, + libgl, + target, + nvstrcat(usrlib, libgl, NULL), + FILE_TYPE_OPENGL_SYMLINK, + FILE_TLS_CLASS_NONE, + FILE_COMPAT_ARCH_NATIVE, + 0000); + } else { + nvfree(libgl); + } + + nvfree(opengl_path); + nvfree(opengl32_path); +} @@ -38,10 +38,8 @@ int get_prefixes(Options *op); /* XXX move? */ int add_kernel_modules_to_package(Options *op, Package *p); void remove_non_kernel_module_files_from_package(Options *op, Package *p); void remove_opengl_files_from_package(Options *op, Package *p); -void remove_trailing_slashes(char *s); int mode_string_to_mode(Options *op, char *s, mode_t *mode); char *mode_to_permission_string(mode_t mode); -int directory_exists(Options *op, const char *dir); int confirm_path(Options *op, const char *path); int mkdir_recursive(Options *op, const char *path, const mode_t mode, int log); int mkdir_with_log(Options *op, const char *path, const mode_t mode); @@ -66,9 +64,12 @@ void process_libGL_la_files(Options *op, Package *p); void process_dot_desktop_files(Options *op, Package *p); int set_security_context(Options *op, const char *filename); void get_default_prefixes_and_paths(Options *op); +void get_compat32_path(Options *op); char *nv_strreplace(char *src, char *orig, char *replace); char *get_filename(Options *op, const char *def, const char *msg); int secure_delete(Options *op, const char *file); void invalidate_package_entry(PackageEntry *entry); +int is_subdirectory(const char *dir, const char *subdir, int *is_subdir); +void add_libgl_abi_symlink(Options *op, Package *p); #endif /* __NVIDIA_INSTALLER_FILES_H__ */ diff --git a/install-from-cwd.c b/install-from-cwd.c index 523cb57..64fc6d4 100644 --- a/install-from-cwd.c +++ b/install-from-cwd.c @@ -76,12 +76,11 @@ int install_from_cwd(Options *op) { Package *p; CommandList *c; - const char *msg; int ret; int ran_pre_install_hook = FALSE; HookScriptStatus res; - static const char edit_your_xf86config[] = + 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."; @@ -93,6 +92,10 @@ int install_from_cwd(Options *op) if ((p = parse_manifest(op)) == NULL) goto failed; + if (!op->x_files_packaged) { + edit_your_xf86config = ""; + } + ui_set_title(op, "%s (%s)", p->description, p->version); /* @@ -248,6 +251,15 @@ int install_from_cwd(Options *op) */ if (!set_destinations(op, p)) goto failed; + + /* + * if we are installing OpenGL libraries, ensure that a symlink gets + * installed to /usr/lib/libGL.so.1. add_libgl_abi_symlink() sets its own + * destination, so it must be called after set_destinations(). + */ + if (!op->kernel_module_only && !op->no_opengl_files) { + add_libgl_abi_symlink(op, p); + } /* * uninstall the existing driver; this needs to be done before @@ -296,6 +308,23 @@ int install_from_cwd(Options *op) if (op->dkms && !dkms_install_module(op, p->version, get_kernel_name(op))) goto failed; + /* Make sure the RM is loaded */ + + if (!op->no_kernel_module || op->dkms) { + /* + * If a kernel module was installed the normal way, it should have been + * left loaded by test_kernel_module(). However, older versions of + * nvidia-uninstall don't honor the --skip-module-unload option, so + * uninstalling a previous driver may have unloaded the module that + * test_kernel_module() loaded. Just in case that happened, modprobe it + * again here. + * + * When installing the module via DKMS, the module is not loaded to + * begin with. + */ + if (!load_kernel_module(op, p)) goto failed; + } + /* run the distro postinstall script */ run_distro_hook(op, "post-install"); @@ -307,7 +336,6 @@ int install_from_cwd(Options *op) check_installed_files_from_package(op, p); - if (!check_sysvipc(op)) goto failed; if (!check_runtime_configuration(op, p)) goto failed; /* done */ @@ -321,28 +349,22 @@ int install_from_cwd(Options *op) /* ask the user if they would like to run nvidia-xconfig */ - ret = ui_yes_no(op, op->run_nvidia_xconfig, - "Would you like to run the nvidia-xconfig utility " - "to automatically update your X configuration file " - "so that the NVIDIA X driver will be used when you " - "restart X? Any pre-existing X configuration " - "file will be backed up."); + const char *msg = "Would you like to run the nvidia-xconfig utility " + "to automatically update your X configuration file " + "so that the NVIDIA X driver will be used when you " + "restart X? Any pre-existing X configuration " + "file will be backed up."; - if (ret) { - ret = run_nvidia_xconfig(op, FALSE); - } + ret = run_nvidia_xconfig(op, FALSE, msg, op->run_nvidia_xconfig); if (ret) { ui_message(op, "Your X configuration file has been successfully " "updated. Installation of the %s (version: %s) is now " "complete.", p->description, p->version); } else { - - msg = edit_your_xf86config; - ui_message(op, "Installation of the %s (version: %s) is now " "complete. %s", p->description, - p->version, msg); + p->version, edit_your_xf86config); } } @@ -453,7 +475,7 @@ dkmscatfailed: * will be installed somewhere. Don't offer DKMS as an option if module * signing was requested. */ - if (find_system_util("dkms") && !op->no_kernel_module_source && + if (op->utils[DKMS] && !op->no_kernel_module_source && !(op->module_signing_secret_key && op->module_signing_public_key)) { op->dkms = ui_yes_no(op, op->dkms, "Would you like to register the kernel module " @@ -492,14 +514,15 @@ dkmscatfailed: if ((precompiled_info = find_precompiled_kernel_interface(op, p))) { - int i; + int i, precompiled_success = TRUE; /* * 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; + precompiled_success = FALSE; + goto precompiled_done; } /* @@ -515,10 +538,15 @@ dkmscatfailed: for (i = 0; i < precompiled_info->num_files; i++) { if (!link_kernel_module(op, p, p->kernel_module_build_directory, &(precompiled_info->files[i]))) { - return FALSE; + precompiled_success = FALSE; + goto precompiled_done; } } - +precompiled_done: + free_precompiled(precompiled_info); + if (!precompiled_success) { + return FALSE; + } } else { /* * make sure the required development tools are present on @@ -624,6 +652,49 @@ int add_this_kernel(Options *op) +static void add_conflicting_file(Package *p, int *index, const char *file) +{ + char *c; + + p->conflicting_files = nvrealloc(p->conflicting_files, + sizeof(ConflictingFileInfo) * (*index+1)); + + p->conflicting_files[*index].name = file; + + if (file == NULL) { + /* Adding a terminator to the list. Pretend that the name is + * actually an empty string to avoid crashing later. */ + file = ""; + } + + /* + * match the names of DSOs with "libfoo.so*" by stopping any comparisons + * after ".so". + */ + + c = strstr(file, ".so."); + if (c) { + p->conflicting_files[*index].len = (c - file) + 3; + } else { + p->conflicting_files[*index].len = strlen(file); + } + + /* + * XXX avoid conflicting with libglx.so if it doesn't include the string + * "glxModuleData" to avoid removing the wrong libglx.so (bug 489316) + */ + + if (strncmp(file, "libglx.so", p->conflicting_files[*index].len) == 0) { + p->conflicting_files[*index].requiredString = "glxModuleData"; + } else { + p->conflicting_files[*index].requiredString = NULL; + } + + (*index)++; +} + + + /* * parse_manifest() - open and read the .manifest file in the current * directory. @@ -656,13 +727,14 @@ int add_this_kernel(Options *op) static Package *parse_manifest (Options *op) { - char *buf, *c, *flag, *tmpstr, *module_suffix = ""; - int done, n, line; + char *buf, *c, *tmpstr, *module_suffix = "", *interface_suffix = ""; + int n, line; int fd, ret, len = 0; struct stat stat_buf; Package *p; char *manifest = MAP_FAILED, *ptr; int opengl_files_packaged = FALSE; + int num_conflicting_files = 0; p = (Package *) nvalloc(sizeof (Package)); @@ -707,21 +779,22 @@ static Package *parse_manifest (Options *op) if (op->multiple_kernel_modules) { module_suffix = "0"; + interface_suffix = "-0"; } p->kernel_module_name = nvstrcat(tmpstr, module_suffix, NULL); p->kernel_module_filename = nvstrcat(p->kernel_module_name, ".ko", NULL); - p->kernel_interface_filename = nvstrcat("nv-linux", module_suffix, ".o", NULL); + p->kernel_interface_filename = nvstrcat("nv-linux", interface_suffix, ".o", NULL); p->kernel_frontend_module_name = nvstrcat(tmpstr, "-frontend", NULL); p->kernel_frontend_module_filename = nvstrcat(p->kernel_frontend_module_name, ".ko", NULL); - p->kernel_frontend_interface_filename = "nv-linuxfrontend.o"; + p->kernel_frontend_interface_filename = "nv-linux-frontend.o"; p->uvm_kernel_module_name = nvstrcat(tmpstr, "-uvm", NULL); p->uvm_kernel_module_filename = nvstrcat(p->uvm_kernel_module_name, ".ko", NULL); - p->uvm_interface_filename = "nv-linuxuvm.o"; + p->uvm_interface_filename = "nv-linux-uvm.o"; nvfree(tmpstr); @@ -790,166 +863,195 @@ static Package *parse_manifest (Options *op) /* the rest of the file is file entries */ - done = FALSE; line++; - do { - buf = get_next_line(ptr, &ptr, manifest, len); - if (!buf) { - done = TRUE; - } else if (buf[0] == '\0') { + for (; (buf = get_next_line(ptr, &ptr, manifest, len)); line++) { + char *flag = NULL; + PackageEntry entry; + int entry_success = FALSE; + + if (buf[0] == '\0') { free(buf); - done = TRUE; - } else { - PackageEntry entry; - - /* initialize the new entry */ + break; + } - memset(&entry, 0, sizeof(PackageEntry)); + /* initialize the new entry */ - /* read the file name and permissions */ + memset(&entry, 0, sizeof(PackageEntry)); - c = buf; + /* read the file name and permissions */ - entry.file = read_next_word(buf, &c); + c = buf; - if (!entry.file) goto invalid_manifest_file; + entry.file = read_next_word(buf, &c); - tmpstr = read_next_word(c, &c); - - if (!tmpstr) goto invalid_manifest_file; - - /* translate the mode string into an octal mode */ - - ret = mode_string_to_mode(op, tmpstr, &entry.mode); + if (!entry.file) goto entry_done; - free(tmpstr); + tmpstr = read_next_word(c, &c); - if (!ret) goto invalid_manifest_file; - - /* every file has a type field */ + if (!tmpstr) goto entry_done; - entry.type = FILE_TYPE_NONE; + /* translate the mode string into an octal mode */ - flag = read_next_word(c, &c); - if (!flag) goto invalid_manifest_file; + ret = mode_string_to_mode(op, tmpstr, &entry.mode); - entry.type = parse_manifest_file_type(flag, &entry.caps); + free(tmpstr); - if (entry.type == FILE_TYPE_NONE) { - nvfree(flag); - goto invalid_manifest_file; - } + if (!ret) goto entry_done; + + /* every file has a type field */ - /* if any UVM files have been packaged, set uvm_files_packaged. */ + entry.type = FILE_TYPE_NONE; - if (entry.type == FILE_TYPE_UVM_MODULE_SRC) { + flag = read_next_word(c, &c); + if (!flag) goto entry_done; + + entry.type = parse_manifest_file_type(flag, &entry.caps); + + if (entry.type == FILE_TYPE_NONE) { + goto entry_done; + } + + /* Track whether certain file types were packaged */ + + switch (entry.type) { + case FILE_TYPE_UVM_MODULE_SRC: op->uvm_files_packaged = TRUE; - } + break; + case FILE_TYPE_XMODULE_SHARED_LIB: + op->x_files_packaged = TRUE; + break; + default: break; + } - /* set opengl_files_packaged if any OpenGL files were packaged */ + /* set opengl_files_packaged if any OpenGL files were packaged */ - if (entry.caps.is_opengl) { - opengl_files_packaged = TRUE; - } + if (entry.caps.is_opengl) { + opengl_files_packaged = TRUE; + } + + /* some libs/symlinks have an arch field */ + + entry.compat_arch = FILE_COMPAT_ARCH_NONE; + if (entry.caps.has_arch) { nvfree(flag); + flag = read_next_word(c, &c); + if (!flag) goto entry_done; + + if (strcmp(flag, "COMPAT32") == 0) + entry.compat_arch = FILE_COMPAT_ARCH_COMPAT32; + else if (strcmp(flag, "NATIVE") == 0) + entry.compat_arch = FILE_COMPAT_ARCH_NATIVE; + else { + goto entry_done; + } + } - /* some libs/symlinks have an arch field */ + /* if compat32 files are packaged, set compat32_files_packaged */ - entry.compat_arch = FILE_COMPAT_ARCH_NONE; + if (entry.compat_arch == FILE_COMPAT_ARCH_COMPAT32) { + op->compat32_files_packaged = TRUE; + } - if (entry.caps.has_arch) { - flag = read_next_word(c, &c); - if (!flag) goto invalid_manifest_file; + /* some libs/symlinks have a class field */ - if (strcmp(flag, "COMPAT32") == 0) - entry.compat_arch = FILE_COMPAT_ARCH_COMPAT32; - else if (strcmp(flag, "NATIVE") == 0) - entry.compat_arch = FILE_COMPAT_ARCH_NATIVE; - else { - nvfree(flag); - goto invalid_manifest_file; - } + entry.tls_class = FILE_TLS_CLASS_NONE; - nvfree(flag); + if (entry.caps.has_tls_class) { + nvfree(flag); + flag = read_next_word(c, &c); + if (!flag) goto entry_done; + + if (strcmp(flag, "CLASSIC") == 0) + entry.tls_class = FILE_TLS_CLASS_CLASSIC; + else if (strcmp(flag, "NEW") == 0) + entry.tls_class = FILE_TLS_CLASS_NEW; + else { + goto entry_done; } + } - /* some libs/symlinks have a class field */ + /* libs and documentation have a path field */ - entry.tls_class = FILE_TLS_CLASS_NONE; + if (entry.caps.has_path) { + entry.path = read_next_word(c, &c); + if (!entry.path) goto invalid_manifest_file; + } else { + entry.path = NULL; + } - if (entry.caps.has_tls_class) { - flag = read_next_word(c, &c); - if (!flag) goto invalid_manifest_file; + /* symlinks have a target */ - if (strcmp(flag, "CLASSIC") == 0) - entry.tls_class = FILE_TLS_CLASS_CLASSIC; - else if (strcmp(flag, "NEW") == 0) - entry.tls_class = FILE_TLS_CLASS_NEW; - else { - nvfree(flag); - goto invalid_manifest_file; - } + if (entry.caps.is_symlink) { + entry.target = read_next_word(c, &c); + if (!entry.target) goto invalid_manifest_file; + } else { + entry.target = NULL; + } - nvfree(flag); - } + /* + * as a convenience for later, set the 'name' pointer to + * the basename contained in 'file' (ie the portion of + * 'file' without any leading directory components + */ - /* libs and documentation have a path field */ + entry.name = strrchr(entry.file, '/'); + if (entry.name) entry.name++; - if (entry.caps.has_path) { - entry.path = read_next_word(c, &c); - if (!entry.path) goto invalid_manifest_file; - } else { - entry.path = NULL; - } - - /* symlinks have a target */ + if (!entry.name) entry.name = entry.file; - if (entry.caps.is_symlink) { - entry.target = read_next_word(c, &c); - if (!entry.target) goto invalid_manifest_file; - } else { - entry.target = NULL; - } + add_package_entry(p, + entry.file, + entry.path, + entry.name, + entry.target, + entry.dst, + entry.type, + entry.tls_class, + entry.compat_arch, + entry.mode); + + + /* Conflict with any non-wrapper shared libs. Don't conflict with + * OpenGL files if we won't be installing any. */ + if (entry.caps.is_shared_lib && !entry.caps.is_wrapper && + (!entry.caps.is_opengl || !op->no_opengl_files)) { + add_conflicting_file(p, &num_conflicting_files, entry.name); + } - /* - * as a convenience for later, set the 'name' pointer to - * the basename contained in 'file' (ie the portion of - * 'file' without any leading directory components - */ + entry_success = TRUE; - entry.name = strrchr(entry.file, '/'); - if (entry.name) entry.name++; - - if (!entry.name) entry.name = entry.file; + entry_done: + /* clean up */ - 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 */ - - free(buf); + nvfree(buf); + nvfree(flag); + if (!entry_success) { + goto invalid_manifest_file; } - - line++; + } - } while (!done); + /* If no OpenGL files were packaged, we can't install them. Set the + * no_opengl_files flag so that everything we skip when explicitly + * excluding OpenGL is also skipped when OpenGL is not packaged. */ - /* If the package does not contain any OpenGL files, do not install - * OpenGL files */ if (!opengl_files_packaged) { op->no_opengl_files = TRUE; } + /* XXX always conflict with these files if OpenGL files will be installed + * libglamoregl.so: prevent X from loading libGL and libglx simultaneously + * (bug 1299091) + * libGLwrapper.so: this library has an SONAME of libGL.so.1 (bug 74761) */ + if (!op->no_opengl_files) { + add_conflicting_file(p, &num_conflicting_files, "libglamoregl.so"); + add_conflicting_file(p, &num_conflicting_files, "libGLwrapper.so"); + } + + /* terminate the conflicting files list */ + add_conflicting_file(p, &num_conflicting_files, NULL); + munmap(manifest, len); if (fd != -1) close(fd); @@ -1327,13 +1429,13 @@ generate_done: if (op->multiple_kernel_modules) { if (!sign_kernel_module(op, p->kernel_module_build_directory, - "frontend", TRUE)) { + "-frontend", TRUE)) { return FALSE; } } if (op->install_uvm) { - if (!sign_kernel_module(op, p->uvm_module_build_directory, "uvm", + if (!sign_kernel_module(op, p->uvm_module_build_directory, "-uvm", TRUE)) { return FALSE; } @@ -1391,7 +1493,7 @@ generate_done: } else { /* Remove any ':' characters from fingerprint and truncate */ char *tmp = nv_strreplace(fingerprint, ":", ""); - strncpy(short_fingerprint, tmp, sizeof(fingerprint)); + strncpy(short_fingerprint, tmp, sizeof(short_fingerprint)); nvfree(tmp); } short_fingerprint[sizeof(short_fingerprint) - 1] = '\0'; @@ -220,7 +220,7 @@ int determine_kernel_source_path(Options *op, Package *p) result = ui_get_input(op, op->kernel_source_path, "Kernel source path"); if (result && result[0]) { - if (!directory_exists(op, result)) { + if (!directory_exists(result)) { ui_warn(op, "Kernel source path '%s' does not exist.", result); free(result); @@ -272,7 +272,7 @@ int determine_kernel_source_path(Options *op, Package *p) /* check that the kernel source path exists */ - if (!directory_exists(op, op->kernel_source_path)) { + if (!directory_exists(op->kernel_source_path)) { ui_error (op, "The kernel source path '%s' does not exist. %s", op->kernel_source_path, install_your_kernel_source); op->kernel_source_path = NULL; @@ -364,7 +364,7 @@ int determine_kernel_output_path(Options *op) "'--kernel-output-path' commandline option.", op->kernel_output_path); - if (!directory_exists(op, op->kernel_output_path)) { + if (!directory_exists(op->kernel_output_path)) { ui_error(op, "The kernel output path '%s' does not exist.", op->kernel_output_path); op->kernel_output_path = NULL; @@ -382,7 +382,7 @@ int determine_kernel_output_path(Options *op) "SYSOUT environment variable.", str); op->kernel_output_path = str; - if (!directory_exists(op, op->kernel_output_path)) { + if (!directory_exists(op->kernel_output_path)) { ui_error(op, "The kernel output path '%s' does not exist.", op->kernel_output_path); op->kernel_output_path = NULL; @@ -404,7 +404,7 @@ int determine_kernel_output_path(Options *op) nvfree(str); str = nvstrcat("/lib/modules/", tmp, "/build", NULL); - if (directory_exists(op, str)) { + if (directory_exists(str)) { op->kernel_output_path = str; return TRUE; } @@ -450,13 +450,9 @@ static int attach_signature(Options *op, Package *p, if (module_file && fileInfo->signature_size) { command_ret = fwrite(fileInfo->signature, 1, fileInfo->signature_size, module_file); - if (command_ret != fileInfo->signature_size) { - goto attach_done; + if (command_ret == fileInfo->signature_size) { + op->kernel_module_signed = ret = !ferror(module_file); } - - op->kernel_module_signed = ret = !ferror(module_file); -attach_done: - fclose(module_file); } else { ret = (ui_multiple_choice(op, choices, 2, 1, "A detached signature was included with " @@ -467,6 +463,10 @@ attach_done: "still like to install the unsigned " "kernel module?") == 0); } + + if (module_file) { + fclose(module_file); + } } else { ret = (ui_multiple_choice(op, choices, 2, 1, "A detached signature was included with the " @@ -578,22 +578,25 @@ static int build_kernel_module_helper(Options *op, const char *dir, const char *module, int num_instances) { int ret; - char *instances = NULL, *cmd, *tmp; + char *instances = NULL, *cmd, *tmp, *concurrency; tmp = op->multiple_kernel_modules && num_instances ? nvasprintf("%d", num_instances) : NULL; instances = nvstrcat(" NV_BUILD_MODULE_INSTANCES=", tmp, NULL); nvfree(tmp); + concurrency = nvasprintf(" -j%d ", op->concurrency_level); + tmp = nvasprintf("Building %s kernel module:", module); ui_status_begin(op, tmp, "Building"); nvfree(tmp); cmd = nvstrcat("cd ", dir, "; ", op->utils[MAKE], " module", " SYSSRC=", op->kernel_source_path, - " SYSOUT=", op->kernel_output_path, + " SYSOUT=", op->kernel_output_path, concurrency, instances, NULL); nvfree(instances); + nvfree(concurrency); ret = run_command(op, cmd, NULL, TRUE, 25, TRUE); @@ -736,7 +739,7 @@ int sign_kernel_module(Options *op, const char *build_directory, const char *module_suffix, int status) { char *cmd, *mod_sign_cmd, *mod_sign_hash; int ret, success; - char *build_module_instances_parameter; + char *build_module_instances_parameter, *concurrency; /* if module_signing_script isn't set, then set mod_sign_cmd below to end * the nvstrcat() that builds cmd early. */ @@ -762,15 +765,17 @@ int sign_kernel_module(Options *op, const char *build_directory, build_module_instances_parameter = nvstrdup(""); } + concurrency = nvasprintf(" -j%d ", op->concurrency_level); 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, " MODPUBKEY=", op->module_signing_public_key, - " NV_MODULE_SUFFIX=", module_suffix, + " BUILD_MODULES_LIST=\"nvidia", module_suffix, "\" ", build_module_instances_parameter, mod_sign_cmd ? mod_sign_cmd : "", - mod_sign_hash ? mod_sign_hash : "", NULL); + mod_sign_hash ? mod_sign_hash : "", concurrency, NULL); + nvfree(concurrency); ret = run_command(op, cmd, NULL, TRUE, 20 /* XXX */, TRUE); success = ret == 0; @@ -878,11 +883,11 @@ done: static int build_kernel_interface_file(Options *op, const char *tmpdir, PrecompiledFileInfo *fileInfo, - const char *kernel_interface_filename, - const char *module_suffix) + const char *kernel_interface_filename) { char *cmd; char *kernel_interface, *build_module_instances_parameter = NULL; + char *concurrency; int ret; if (op->multiple_kernel_modules) { @@ -890,14 +895,16 @@ static int build_kernel_interface_file(Options *op, const char *tmpdir, nvasprintf(" NV_BUILD_MODULE_INSTANCES=%d", NV_MAX_MODULE_INSTANCES); } + concurrency = nvasprintf(" -j%d ", op->concurrency_level); + cmd = nvstrcat("cd ", tmpdir, "; ", op->utils[MAKE], " ", kernel_interface_filename, " SYSSRC=", op->kernel_source_path, - " SYSOUT=", op->kernel_output_path, - " NV_MODULE_SUFFIX=", module_suffix, + " SYSOUT=", op->kernel_output_path, concurrency, build_module_instances_parameter, NULL); nvfree(build_module_instances_parameter); + nvfree(concurrency); ret = run_command(op, cmd, NULL, TRUE, 25 /* XXX */, TRUE); @@ -978,7 +985,7 @@ static int build_and_pack_interface(Options *op, Package *p, const char *tmpdir, interface); dir = nvstrcat(tmpdir, "/", subdir, NULL); - ret = build_kernel_interface_file(op, dir, fileInfo, interface, suffix); + ret = build_kernel_interface_file(op, dir, fileInfo, interface); if (!ret) { goto done; @@ -1020,7 +1027,6 @@ int build_kernel_interface(Options *op, Package *p, PrecompiledFileInfo ** fileInfos) { char *tmpdir = NULL; - char *dstfile = NULL; int files_packaged = 0, i; int num_files = 1, ret = FALSE; char *uvmdir = NULL; @@ -1119,7 +1125,7 @@ interface_done: ret = build_and_pack_interface(op, p, tmpdir, "", *fileInfos + num_files, p->kernel_frontend_interface_filename, p->kernel_frontend_module_filename, - "frontend", ""); + "-frontend", ""); if (!ret) { goto failed; } @@ -1131,7 +1137,7 @@ interface_done: ret = build_and_pack_interface(op, p, tmpdir, UVM_SUBDIR, *fileInfos + files_packaged, p->uvm_interface_filename, - p->uvm_kernel_module_filename, "uvm", ""); + p->uvm_kernel_module_filename, "-uvm", ""); if (!ret) { goto failed; @@ -1153,8 +1159,6 @@ failed: nvfree(tmpdir); } - if (dstfile) nvfree(dstfile); - return files_packaged; } /* build_kernel_interface() */ @@ -1449,8 +1453,8 @@ static int ignore_load_error(Options *op, Package *p, /* - * test_kernel_module() - attempt to insmod the kernel module and then - * rmmod it. Return TRUE if the insmod succeeded, or FALSE otherwise. + * test_kernel_module() - attempt to insmod the kernel modules and then rmmod + * nvidia-uvm. Return TRUE if the insmod succeeded, or FALSE otherwise. */ int test_kernel_module(Options *op, Package *p) @@ -1559,9 +1563,14 @@ int test_kernel_module(Options *op, Package *p) check_for_warning_messages(op); /* - * attempt to unload the kernel module, but don't abort if - * this fails: the kernel may not have been configured with - * support for module unloading (Linux 2.6). + * attempt to unload the UVM kernel module, but don't abort if this fails: + * the kernel may not have been configured with support for module unloading + * (Linux 2.6). + * + * The nvidia module is left loaded in case an X server with + * OutputClass-based driver matching is being used. UVM is unloaded to make + * it easier to roll back to older versions of the driver whose installers + * didn't know how to unload the nvidia-uvm module. */ if (op->install_uvm) { @@ -1570,17 +1579,6 @@ int test_kernel_module(Options *op, Package *p) nvfree(cmd); } - cmd = nvstrcat(op->utils[RMMOD], " ", p->kernel_module_name, NULL); - run_command(op, cmd, NULL, FALSE, 0, TRUE); - nvfree(cmd); - - if (op->multiple_kernel_modules) { - cmd = nvstrcat(op->utils[RMMOD], " ", - p->kernel_frontend_module_name, NULL); - run_command(op, cmd, NULL, FALSE, 0, TRUE); - nvfree(cmd); - } - ret = TRUE; test_exit: @@ -1811,12 +1809,12 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p) proc_version_string = read_proc_version(op, op->proc_mount_point); - if (!proc_version_string) goto failed; + if (!proc_version_string) goto done; /* make sure the target directory exists */ if (!mkdir_recursive(op, p->kernel_module_build_directory, 0755, FALSE)) - goto failed; + goto done; memset(search_filelist, 0, sizeof(search_filelist)); @@ -1883,7 +1881,7 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p) "to compile a kernel interface for your kernel.", op->precompiled_kernel_interfaces_url); free_search_filelist(search_filelist); - return NULL; + goto done; } } @@ -1907,21 +1905,18 @@ PrecompiledInfo *find_precompiled_kernel_interface(Options *op, Package *p) } } - if (info) { - return info; - } + done: - failed: + nvfree(proc_version_string); - if (op->expert) { + if (!info && op->expert) { ui_message(op, "No precompiled kernel interface was found to match " "your kernel; this means that the installer will need to " "compile a new kernel interface."); } - return NULL; - -} /* find_precompiled_kernel_interface() */ + return info; +} @@ -2022,7 +2017,7 @@ static char *default_kernel_module_installation_path(Options *op) str = nvstrcat("/lib/modules/", tmp, "/kernel", NULL); - if (directory_exists(op, str)) { + if (directory_exists(str)) { free(str); str = nvstrcat("/lib/modules/", tmp, "/kernel/drivers/video", NULL); return str; @@ -2114,7 +2109,7 @@ static char *default_kernel_source_path(Options *op) if (tmp) { str = nvstrcat("/lib/modules/", tmp, "/source", NULL); - if (directory_exists(op, str)) { + if (directory_exists(str)) { return str; } @@ -2122,7 +2117,7 @@ static char *default_kernel_source_path(Options *op) str = nvstrcat("/lib/modules/", tmp, "/build", NULL); - if (directory_exists(op, str)) { + if (directory_exists(str)) { return str; } @@ -2134,7 +2129,7 @@ static char *default_kernel_source_path(Options *op) */ str = nvstrcat("/usr/src/linux-", tmp, NULL); - if (directory_exists(op, str)) { + if (directory_exists(str)) { return str; } @@ -2143,7 +2138,7 @@ static char *default_kernel_source_path(Options *op) /* finally, try /usr/src/linux */ - if (directory_exists(op, "/usr/src/linux")) { + if (directory_exists("/usr/src/linux")) { return "/usr/src/linux"; } @@ -2294,12 +2289,12 @@ download_updated_kernel_interface(Options *op, Package *p, { int fd = -1; int dst_fd = -1; - int length, i; + int length = 0, i; char *url = NULL; char *tmpfile = NULL; char *dstfile = NULL; char *buf = NULL; - char *str = (void *) -1; + char *str = MAP_FAILED; char *ptr, *s; struct stat stat_buf; PrecompiledInfo *info = NULL; @@ -2334,7 +2329,7 @@ download_updated_kernel_interface(Options *op, Package *p, /* map the file into memory for easier reading */ str = mmap(0, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0); - if (str == (void *) -1) goto done; + if (str == MAP_FAILED) goto done; /* * loop over each line of the updates file: each line should be of @@ -2431,19 +2426,18 @@ download_updated_kernel_interface(Options *op, Package *p, done: - if (dstfile) nvfree(dstfile); - if (buf) nvfree(buf); - if (str != (void *) -1) munmap(str, stat_buf.st_size); + nvfree(dstfile); + nvfree(buf); + if (str != MAP_FAILED) munmap(str, length); if (dst_fd > 0) close(dst_fd); if (fd > 0) close(fd); unlink(tmpfile); - if (tmpfile) nvfree(tmpfile); - if (url) nvfree(url); + nvfree(tmpfile); + nvfree(url); return info; - -} /* get_updated_kernel_interfaces() */ +} @@ -32,7 +32,8 @@ _is_symlink, \ _is_shared_lib, \ _is_opengl, \ - _is_temporary) \ + _is_temporary, \ + _is_wrapper) \ #_name , FILE_TYPE_ ## _name , \ { \ .has_arch = _has_arch, \ @@ -43,6 +44,7 @@ .is_shared_lib = _is_shared_lib, \ .is_opengl = _is_opengl, \ .is_temporary = _is_temporary, \ + .is_wrapper = _is_wrapper, \ } /* @@ -56,62 +58,65 @@ static const struct { } packageEntryFileTypeTable[] = { /* - * is_temporary ------------------------------------+ - * is_opengl ---------------------------------+ | - * is_shared_lib ------------------------------+ | | - * is_symlink ---------------------------+ | | | - * has_path ------------------------+ | | | | - * installable ---------------------+ | | | | | - * has_tls_class ------------------+ | | | | | | - * has_arch ---------------+ | | | | | | | - * | | | | | | | | + * is_wrapper ---------------------------------------+ + * is_temporary ------------------------------------+ | + * is_opengl ---------------------------------+ | | + * is_shared_lib ------------------------------+ | | | + * is_symlink ---------------------------+ | | | | + * has_path ------------------------+ | | | | | + * installable ---------------------+ | | | | | | + * has_tls_class ------------------+ | | | | | | | + * has_arch ---------------+ | | | | | | | | + * | | | | | | | | | */ - { ENTRY(KERNEL_MODULE_SRC, F, F, T, F, F, F, F, F ) }, - { ENTRY(KERNEL_MODULE_CMD, F, F, F, F, F, F, F, F ) }, - { ENTRY(KERNEL_MODULE, F, F, T, F, F, F, F, F ) }, - { ENTRY(OPENGL_HEADER, F, F, T, T, F, F, T, F ) }, - { ENTRY(CUDA_ICD, F, F, T, F, F, F, F, F ) }, - { ENTRY(OPENGL_LIB, T, F, T, F, F, T, T, F ) }, - { ENTRY(CUDA_LIB, T, F, T, T, F, T, F, F ) }, - { ENTRY(LIBGL_LA, T, F, T, F, F, F, T, T ) }, - { ENTRY(XLIB_STATIC_LIB, F, F, T, F, F, F, F, F ) }, - { ENTRY(XLIB_SHARED_LIB, F, F, T, F, F, T, F, F ) }, - { ENTRY(TLS_LIB, T, T, T, T, F, T, T, F ) }, - { ENTRY(UTILITY_LIB, T, F, T, F, F, T, F, F ) }, - { ENTRY(DOCUMENTATION, F, F, T, T, F, F, F, F ) }, - { ENTRY(APPLICATION_PROFILE, F, F, T, T, F, F, F, F ) }, - { ENTRY(MANPAGE, F, F, T, T, F, F, F, F ) }, - { ENTRY(EXPLICIT_PATH, F, F, T, T, F, F, F, F ) }, - { ENTRY(OPENGL_SYMLINK, T, F, F, F, T, F, T, F ) }, - { ENTRY(CUDA_SYMLINK, T, F, F, T, T, F, F, F ) }, - { ENTRY(XLIB_SYMLINK, F, F, F, F, T, F, F, F ) }, - { ENTRY(TLS_SYMLINK, T, T, F, T, T, F, T, F ) }, - { ENTRY(UTILITY_LIB_SYMLINK, T, F, F, F, T, F, F, F ) }, - { ENTRY(INSTALLER_BINARY, F, F, T, F, F, F, F, F ) }, - { ENTRY(UTILITY_BINARY, F, F, T, F, F, F, F, F ) }, - { ENTRY(UTILITY_BIN_SYMLINK, F, F, F, F, T, F, F, F ) }, - { ENTRY(DOT_DESKTOP, F, F, T, T, F, F, F, T ) }, - { ENTRY(XMODULE_SHARED_LIB, F, F, T, T, F, T, F, F ) }, - { ENTRY(XMODULE_SYMLINK, F, F, F, T, T, F, F, F ) }, - { ENTRY(GLX_MODULE_SHARED_LIB, F, F, T, T, F, T, T, F ) }, - { ENTRY(GLX_MODULE_SYMLINK, F, F, F, T, T, F, T, F ) }, - { ENTRY(XMODULE_NEWSYM, F, F, F, T, T, F, F, F ) }, - { ENTRY(VDPAU_LIB, T, F, T, T, F, T, F, F ) }, - { ENTRY(VDPAU_WRAPPER_LIB, T, F, T, T, F, T, F, F ) }, - { ENTRY(VDPAU_SYMLINK, T, F, F, T, T, F, F, F ) }, - { ENTRY(VDPAU_WRAPPER_SYMLINK, T, F, F, T, T, F, F, F ) }, - { ENTRY(NVCUVID_LIB, T, F, T, F, F, T, F, F ) }, - { ENTRY(NVCUVID_LIB_SYMLINK, T, F, F, F, T, F, F, F ) }, - { ENTRY(ENCODEAPI_LIB, T, F, T, F, F, T, F, F ) }, - { ENTRY(ENCODEAPI_LIB_SYMLINK, T, F, F, F, T, F, F, F ) }, - { ENTRY(VGX_LIB, F, F, T, F, F, T, F, F ) }, - { ENTRY(VGX_LIB_SYMLINK, F, F, F, F, T, F, F, F ) }, - { ENTRY(NVIDIA_MODPROBE, F, F, T, T, F, F, F, F ) }, - { ENTRY(NVIDIA_MODPROBE_MANPAGE,F, F, T, T, F, F, F, F ) }, - { ENTRY(MODULE_SIGNING_KEY, F, F, T, F, F, F, F, T ) }, - { ENTRY(NVIFR_LIB, T, F, T, F, F, T, F, F ) }, - { ENTRY(NVIFR_LIB_SYMLINK, T, F, F, F, T, F, F, F ) }, - { ENTRY(UVM_MODULE_SRC, F, F, T, F, F, F, F, F ) }, + { ENTRY(KERNEL_MODULE_SRC, F, F, T, F, F, F, F, F, F) }, + { ENTRY(KERNEL_MODULE_CMD, F, F, F, F, F, F, F, F, F) }, + { ENTRY(KERNEL_MODULE, F, F, T, F, F, F, F, F, F) }, + { ENTRY(OPENGL_HEADER, F, F, T, T, F, F, T, F, F) }, + { ENTRY(CUDA_ICD, F, F, T, F, F, F, F, F, F) }, + { ENTRY(OPENGL_LIB, T, F, T, F, F, T, T, F, F) }, + { ENTRY(CUDA_LIB, T, F, T, T, F, T, F, F, F) }, + { ENTRY(OPENCL_LIB, T, F, T, T, F, T, F, F, F) }, + { ENTRY(OPENCL_WRAPPER_LIB, T, F, T, T, F, T, F, F, T) }, + { ENTRY(OPENCL_LIB_SYMLINK, T, F, F, T, T, F, F, F, F) }, + { ENTRY(OPENCL_WRAPPER_SYMLINK, T, F, F, T, T, F, F, F, T) }, + { ENTRY(LIBGL_LA, T, F, T, F, F, F, T, T, F) }, + { ENTRY(TLS_LIB, T, T, T, T, F, T, T, F, F) }, + { ENTRY(UTILITY_LIB, T, F, T, F, F, T, F, F, F) }, + { ENTRY(DOCUMENTATION, F, F, T, T, F, F, F, F, F) }, + { ENTRY(APPLICATION_PROFILE, F, F, T, T, F, F, F, F, F) }, + { ENTRY(MANPAGE, F, F, T, T, F, F, F, F, F) }, + { ENTRY(EXPLICIT_PATH, F, F, T, T, F, F, F, F, F) }, + { ENTRY(OPENGL_SYMLINK, T, F, F, F, T, F, T, F, F) }, + { ENTRY(CUDA_SYMLINK, T, F, F, T, T, F, F, F, F) }, + { ENTRY(TLS_SYMLINK, T, T, F, T, T, F, T, F, F) }, + { ENTRY(UTILITY_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) }, + { ENTRY(INSTALLER_BINARY, F, F, T, F, F, F, F, F, F) }, + { ENTRY(UTILITY_BINARY, F, F, T, F, F, F, F, F, F) }, + { ENTRY(UTILITY_BIN_SYMLINK, F, F, F, F, T, F, F, F, F) }, + { ENTRY(DOT_DESKTOP, F, F, T, T, F, F, F, T, F) }, + { ENTRY(XMODULE_SHARED_LIB, F, F, T, T, F, T, F, F, F) }, + { ENTRY(XMODULE_SYMLINK, F, F, F, T, T, F, F, F, F) }, + { ENTRY(GLX_MODULE_SHARED_LIB, F, F, T, T, F, T, T, F, F) }, + { ENTRY(GLX_MODULE_SYMLINK, F, F, F, T, T, F, T, F, F) }, + { ENTRY(XMODULE_NEWSYM, F, F, F, T, T, F, F, F, F) }, + { ENTRY(VDPAU_LIB, T, F, T, T, F, T, F, F, F) }, + { ENTRY(VDPAU_WRAPPER_LIB, T, F, T, T, F, T, F, F, T) }, + { ENTRY(VDPAU_SYMLINK, T, F, F, T, T, F, F, F, F) }, + { ENTRY(VDPAU_WRAPPER_SYMLINK, T, F, F, T, T, F, F, F, T) }, + { ENTRY(NVCUVID_LIB, T, F, T, F, F, T, F, F, F) }, + { ENTRY(NVCUVID_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) }, + { ENTRY(ENCODEAPI_LIB, T, F, T, F, F, T, F, F, F) }, + { ENTRY(ENCODEAPI_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) }, + { ENTRY(VGX_LIB, F, F, T, F, F, T, F, F, F) }, + { ENTRY(VGX_LIB_SYMLINK, F, F, F, F, T, F, F, F, F) }, + { ENTRY(NVIDIA_MODPROBE, F, F, T, T, F, F, F, F, F) }, + { ENTRY(NVIDIA_MODPROBE_MANPAGE,F, F, T, T, F, F, F, F, F) }, + { ENTRY(MODULE_SIGNING_KEY, F, F, T, F, F, F, F, T, F) }, + { ENTRY(NVIFR_LIB, T, F, T, F, F, T, F, F, F) }, + { ENTRY(NVIFR_LIB_SYMLINK, T, F, F, F, T, F, F, F, F) }, + { ENTRY(UVM_MODULE_SRC, F, F, T, F, F, F, F, F, F) }, + { ENTRY(XORG_OUTPUTCLASS_CONFIG,F, F, T, F, F, F, F, F, F) }, }; /* @@ -123,7 +128,7 @@ PackageEntryFileCapabilities get_file_type_capabilities( ) { int i; - PackageEntryFileCapabilities nullCaps = { F, F, F, F, F, F, F, F }; + PackageEntryFileCapabilities nullCaps = { F, F, F, F, F, F, F, F, F }; for (i = 0; i < ARRAY_LEN(packageEntryFileTypeTable); i++) { if (type == packageEntryFileTypeTable[i].type) { @@ -192,6 +197,11 @@ void get_installable_file_type_list( continue; } + if ((type == FILE_TYPE_XORG_OUTPUTCLASS_CONFIG) && + !op->xorg_supports_output_class) { + continue; + } + installable_file_types->types[type] = 1; } } @@ -127,16 +127,19 @@ int check_euid(Options *op) int adjust_cwd(Options *op, const char *program_name) { - char *c, *path; - int len; - + char *c; + int success = TRUE; + /* * extract any pathname portion out of the program_name and chdir * to it */ - + c = strrchr(program_name, '/'); if (c) { + int len; + char *path; + len = c - program_name + 1; path = (char *) nvalloc(len + 1); strncpy(path, program_name, len); @@ -145,14 +148,13 @@ int adjust_cwd(Options *op, const char *program_name) if (chdir(path)) { fprintf(stderr, "Unable to chdir to %s (%s)", path, strerror(errno)); - return FALSE; + success = FALSE; } free(path); } - - return TRUE; - -} /* adjust_cwd() */ + + return success; +} /* @@ -292,13 +294,14 @@ int run_command(Options *op, const char *cmd, char **data, int output, * command. */ - if ((stream = popen(cmd2, "r")) == NULL) { + stream = popen(cmd2, "r"); + nvfree(cmd2); + + if (stream == NULL) { ui_error(op, "Failure executing command '%s' (%s).", cmd, strerror(errno)); return errno; } - - free(cmd2); /* * read from the stream, filling and growing buf, until we hit @@ -459,6 +462,7 @@ static const Util __utils[] = { [PKG_CONFIG] = { "pkg-config", "pkg-config" }, [XSERVER] = { "X", "xserver" }, [OPENSSL] = { "openssl", "openssl" }, + [DKMS] = { "dkms", "dkms" }, /* ModuleUtils */ [INSMOD] = { "insmod", "module-init-tools' or 'kmod" }, @@ -592,6 +596,8 @@ int check_proc_modprobe_path(Options *op) char *target = get_resolved_symlink_target(op, found_modprobe); if (target && access(target, F_OK | X_OK) == 0) { found_modprobe = target; + } else { + nvfree(target); } } @@ -606,6 +612,8 @@ int check_proc_modprobe_path(Options *op) if (target && access(target, F_OK | X_OK) == 0) { nvfree(proc_modprobe); proc_modprobe = target; + } else { + nvfree(target); } } @@ -1115,54 +1123,35 @@ void should_install_opengl_headers(Options *op, Package *p) void should_install_compat32_files(Options *op, Package *p) { #if defined(NV_X86_64) - int i, have_compat32_files = FALSE, install_compat32_files; - /* - * first, scan through the package to see if we have any - * 32bit compatibility files to install. - */ - - for (i = 0; i < p->num_entries; i++) { - if (p->entries[i].compat_arch == FILE_COMPAT_ARCH_COMPAT32) { - have_compat32_files = TRUE; - break; - } + /* If there are no compat32 files, there is nothing to do */ + if (!op->compat32_files_packaged) { + op->install_compat32_libs = NV_OPTIONAL_BOOL_FALSE; + return; } - if (!have_compat32_files) - return; + /* Determine where the compatibility libraries should be installed */ + get_compat32_path(op); /* - * Ask the user if the 32-bit compatibility libraries are - * to be installed. If yes, check if the chosen prefix - * exists. If not, notify the user and ask him/her if the - * files are to be installed anyway. + * If the user hasn't explicitly specified whether to install compat32 + * files, ask if the 32-bit compatibility libraries are to be installed. + * If yes, check if the chosen prefix exists. If not, notify the user and + * ask him/her if the files are to be installed anyway. */ - install_compat32_files = ui_yes_no(op, TRUE, - "Install NVIDIA's 32-bit compatibility libraries?"); - - if (install_compat32_files && (op->compat32_chroot != NULL) && - access(op->compat32_chroot, F_OK) < 0) { + if (op->install_compat32_libs == NV_OPTIONAL_BOOL_DEFAULT) { + int ret; - const char *choices[2] = { - "Install compatibility libraries", - "Do not install compatibility libraries" - }; + ret = ui_yes_no(op, TRUE, + "Install NVIDIA's 32-bit 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); + op->install_compat32_libs = ret ? NV_OPTIONAL_BOOL_TRUE : + NV_OPTIONAL_BOOL_FALSE; } - if (!install_compat32_files) { + if (op->install_compat32_libs == NV_OPTIONAL_BOOL_FALSE) { + int i; + for (i = 0; i < p->num_entries; i++) { if (p->entries[i].compat_arch == FILE_COMPAT_ARCH_COMPAT32) { /* invalidate file */ @@ -1343,6 +1332,7 @@ void check_installed_files_from_package(Options *op, Package *p) static int check_symlink(Options *op, const char *target, const char *link, const char *descr) { + int success = TRUE; char *actual_target; actual_target = get_symlink_target(op, link); @@ -1375,12 +1365,12 @@ static int check_symlink(Options *op, const char *target, const char *link, actual_target, target, link); - free(actual_target); - return FALSE; + success = FALSE; } - return TRUE; - -} /* check_symlink() */ + + nvfree(actual_target); + return success; +} @@ -1681,15 +1671,6 @@ static int tls_test_internal(Options *op, int which_tls, return ret; } /* test_tls_internal() */ - -#else /* defined(NV_TLS_TEST) */ - -int tls_test(Options *op, int compat_32_libs) -{ - /* Assume the TLS test passed. */ - return TRUE; -} - #endif /* defined(NV_TLS_TEST) */ @@ -1730,19 +1711,27 @@ static int rtld_test_internal(Options *op, Package *p, int check_runtime_configuration(Options *op, Package *p) { - int ret = TRUE; + int ret = TRUE, which_tls, which_tls_compat32; + +#if defined(NV_TLS_TEST) + which_tls = op->which_tls; + which_tls_compat32 = op->which_tls_compat32; +#else + /* Platforms that don't need the TLS test only support "new" ELF TLS. */ + which_tls = which_tls_compat32 = TLS_LIB_NEW_TLS; +#endif /* NV_TLS_TEST */ ui_status_begin(op, "Running runtime sanity check:", "Checking"); #if defined(NV_X86_64) - ret = rtld_test_internal(op, p, op->which_tls_compat32, + ret = rtld_test_internal(op, p, which_tls_compat32, rtld_test_array_32, rtld_test_array_32_size, TRUE); #endif /* NV_X86_64 */ if (ret == TRUE) { - ret = rtld_test_internal(op, p, op->which_tls, + ret = rtld_test_internal(op, p, which_tls, rtld_test_array, rtld_test_array_size, FALSE); @@ -2015,68 +2004,16 @@ static int rtld_test_internal(Options *op, Package *p, } /* rtld_test_internal() */ -/* - * get_distribution() - determine what distribution this is; only used - * for several bits of distro-specific behavior requested by - * distribution maintainers. - * - * XXX should we provide a commandline option to override this - * detection? - */ - -Distribution get_distribution(Options *op) -{ - FILE *fp; - char *line = NULL, *ptr; - int eof = FALSE; - - if (access("/etc/SuSE-release", F_OK) == 0) return SUSE; - if (access("/etc/UnitedLinux-release", F_OK) == 0) return UNITED_LINUX; - if (access("/etc/gentoo-release", F_OK) == 0) return GENTOO; - if (access("/etc/arch-release", F_OK) == 0) return ARCH; - - /* - * Attempt to determine if the host system is 'Ubuntu Linux' - * based by checking for a line matching DISTRIB_ID=Ubuntu in - * the file /etc/lsb-release. - */ - fp = fopen("/etc/lsb-release", "r"); - if (fp != NULL) { - while (((line = fget_next_line(fp, &eof)) - != NULL) && !eof) { - ptr = strstr(line, "DISTRIB_ID"); - if (ptr != NULL) { - fclose(fp); - while (ptr != NULL && *ptr != '=') ptr++; - if (ptr != NULL && *ptr == '=') ptr++; - if (ptr != NULL && *ptr != '\0') - if (!strcasecmp(ptr, "Ubuntu")) return UBUNTU; - break; - } - } - } - - if (access("/etc/debian_version", F_OK) == 0) return DEBIAN; - - return OTHER; - -} /* get_distribution() */ - - /* * get_xserver_information() - parse the versionString (from `X * -version`) and assign relevant information that we infer from the X * server version. - * - * Note: this implementation should be shared with nvidia-xconfig */ static int get_xserver_information(const char *versionString, - int *isXorg, int *isModular, - int *autoloadsGLX, - int *supportsExtensionSection) + int *supportsOutputClassSection) { #define XSERVER_VERSION_FORMAT_1 "X Window System Version" #define XSERVER_VERSION_FORMAT_2 "X.Org X Server" @@ -2087,18 +2024,15 @@ static int get_xserver_information(const char *versionString, /* check if this is an XFree86 X server */ if (strstr(versionString, "XFree86 Version")) { - *isXorg = FALSE; *isModular = FALSE; - *autoloadsGLX = FALSE; - *supportsExtensionSection = FALSE; return TRUE; } - /* this must be an X.Org X server */ - - *isXorg = TRUE; - /* attempt to parse the major.minor version out of the string */ + /* + * This must be an X.Org X server. Attempt to parse the major.minor version + * out of the string + */ found = FALSE; @@ -2129,30 +2063,13 @@ static int get_xserver_information(const char *versionString, } /* - * supportsExtensionSection: support for the "Extension" xorg.conf - * section was added between X.Org 6.7 and 6.8. To account for - * the X server version wrap, it is easier to check for X servers - * that do not support the Extension section: 6.x (x < 8) X - * servers. + * support for using OutputClass sections to automatically match drivers to + * platform devices was added in X.Org xserver 1.16. */ - - if ((major == 6) && (minor < 8)) { - *supportsExtensionSection = FALSE; + if ((major == 6) || (major == 7) || ((major == 1) && (minor < 16))) { + *supportsOutputClassSection = FALSE; } else { - *supportsExtensionSection = TRUE; - } - - /* - * support for autoloading GLX was added in X.Org 1.5. To account - * for the X server version wrap, it is easier to check for X - * servers that do not support GLX autoloading: 6.x, 7.x, or < 1.5 - * X servers. - */ - - if ((major == 6) || (major == 7) || ((major == 1) && (minor < 5))) { - *autoloadsGLX = FALSE; - } else { - *autoloadsGLX = TRUE; + *supportsOutputClassSection = TRUE; } return TRUE; @@ -2162,23 +2079,23 @@ static int get_xserver_information(const char *versionString, /* - * check_for_modular_xorg() - run the X binary with the '-version' - * command line option and extract the version in an attempt to - * determine if it's part of a modular Xorg release. If the version - * can't be determined, we assume it's not. + * query_xorg_version() - run the X binary with the '-version' + * command line option and extract the version. * - * This should eventually get collapsed with xconfigGetXServerInUse() - * in nvidia-xconfig. + * Using the version, try to infer if it's part of a modular Xorg release. If + * the version can't be determined, we assume it's not. + * + * This function assigns the following fields: + * op->modular_xorg */ #define OLD_VERSION_FORMAT "(protocol Version %d, revision %d, vendor release %d)" #define NEW_VERSION_FORMAT "X Protocol Version %d, Revision %d, Release %d." -int check_for_modular_xorg(Options *op) +void query_xorg_version(Options *op) { char *cmd = NULL, *data = NULL; - int modular_xorg = FALSE; - int dummy, ret; + int ret = FALSE; if (!op->utils[XSERVER]) goto done; @@ -2195,30 +2112,27 @@ int check_for_modular_xorg(Options *op) * modular */ - ret = get_xserver_information(data, - &dummy, /* isXorg */ - &modular_xorg, /* isModular */ - &dummy, /* autoloadsGLX */ - &dummy); /* supportsExtensionSection */ + ret = get_xserver_information(data, &op->modular_xorg, + &op->xorg_supports_output_class); + + /* fall through */ + +done: /* - * if get_xserver_information() failed, assume the X server is not - * modular + * if no X server was found, or querying the version on the command line + * failed, or get_xserver_information() failed, assume the X server is + * modular, but does not support OutputClass sections */ if (!ret) { - modular_xorg = FALSE; + op->modular_xorg = TRUE; + op->xorg_supports_output_class = FALSE; } - /* fall through */ - -done: nvfree(data); nvfree(cmd); - - return modular_xorg; - -} /* check_for_modular_xorg() */ +} /* @@ -2252,8 +2166,12 @@ int check_for_running_x(Options *op) for (i = 0; i < 8; i++) { snprintf(path, 14, "/tmp/.X%1d-lock", i); if (read_text_file(path, &buf) == TRUE) { - sscanf(buf, "%d", &pid); + int num = sscanf(buf, "%d", &pid); nvfree(buf); + if (num != 1) { + ui_warn(op, "Failed to read a pid from X lock file '%s'", path); + return TRUE; + } snprintf(procpath, 17, "/proc/%d", pid); if (access(procpath, F_OK) == 0) { ui_log(op, "The file '%s' exists and appears to contain the " @@ -2491,40 +2409,58 @@ int check_selinux(Options *op) /* * run_nvidia_xconfig() - run the `nvidia-xconfig` utility. Without * any options, this will just make sure the X config file uses the - * NVIDIA driver by default. The restore parameter controls whether - * the --restore-original-backup option is added, which attempts to - * restore the original backed up X config file. + * NVIDIA driver by default. + * + * Parameters: + * + * restore: controls whether the --restore-original-backup option is added, + * which attempts to restore the original backed up X config file. + * question: if this is non-NULL, the user will be asked 'question' as a + * yes or no question, to determine whether to run nvidia-xconfig. + * answer: the default answer to 'question'. + * + * Returns TRUE if nvidia-xconfig ran successfully; returns FALSE if + * nvidia-xconfig ran unsuccessfully, or did not run at all. */ -int run_nvidia_xconfig(Options *op, int restore) +int run_nvidia_xconfig(Options *op, int restore, const char *question, + int default_answer) { - int ret, bRet = TRUE; - char *data = NULL, *cmd = NULL, *args, *nvidia_xconfig; + int ret = FALSE; + char *nvidia_xconfig; nvidia_xconfig = find_system_util("nvidia-xconfig"); if (nvidia_xconfig == NULL) { + /* nvidia-xconfig not found: don't run it or ask any questions */ goto done; } - args = restore ? " --restore-original-backup" : ""; - - cmd = nvstrcat(nvidia_xconfig, args, NULL); - - ret = run_command(op, cmd, &data, FALSE, 0, TRUE); - - if (ret != 0) { - ui_error(op, "Failed to run `%s`:\n%s", cmd, data); - bRet = FALSE; + ret = question ? ui_yes_no(op, default_answer, "%s", question) : TRUE; + + if (ret) { + int cmd_ret; + char *data, *cmd, *args; + + args = restore ? " --restore-original-backup" : ""; + + cmd = nvstrcat(nvidia_xconfig, args, NULL); + + cmd_ret = run_command(op, cmd, &data, FALSE, 0, TRUE); + + if (cmd_ret != 0) { + ui_error(op, "Failed to run `%s`:\n%s", cmd, data); + ret = FALSE; + } + + nvfree(cmd); + nvfree(data); } done: - - nvfree(cmd); - nvfree(data); nvfree(nvidia_xconfig); - return bRet; + return ret; } /* run_nvidia_xconfig() */ @@ -2987,14 +2923,13 @@ int check_for_nouveau(Options *op) static int run_dkms(Options *op, const char* verb, const char *version, const char *kernel, char** out) { - char *cmd, *cmdline, *veropt, *kernopt = NULL, *kernopt_all = ""; + char *cmdline, *veropt, *kernopt = NULL, *kernopt_all = ""; const char *modopt = " -m nvidia"; /* XXX real name is in the Package */ char *output; int ret; /* Fail if DKMS not found */ - cmd = find_system_util("dkms"); - if (!cmd) { + if (!op->utils[DKMS]) { if (strcmp(verb, DKMS_STATUS) != 0) { ui_error(op, "Failed to find dkms on the system!"); } @@ -3012,9 +2947,8 @@ static int run_dkms(Options *op, const char* verb, const char *version, kernopt = kernel ? nvstrcat(" -k ", kernel, NULL) : NULL; } - cmdline = nvstrcat(cmd, verb, modopt, veropt, kernopt_all, kernopt, NULL); - - nvfree(cmd); + cmdline = nvstrcat(op->utils[DKMS], verb, modopt, veropt, + kernopt_all, kernopt, NULL); /* Run DKMS */ ret = run_command(op, cmdline, &output, FALSE, 0, TRUE); @@ -3190,3 +3124,48 @@ ElfFileType get_elf_architecture(const char *filename) default: return ELF_INVALID_FILE; } } + + + +/* + * set_concurrency_level() - automatically determine the concurrency level, + * if the user has not specified it. + */ + +void set_concurrency_level(Options *op) +{ + int detected_cpus; + + if (op->concurrency_level) { + ui_log(op, "Concurrency level set to %d on the command line.", + op->concurrency_level); + } else { +#if defined _SC_NPROCESSORS_ONLN + detected_cpus = sysconf(_SC_NPROCESSORS_ONLN); + + if (detected_cpus >= 1) { + ui_log(op, "Detected %d CPUs online; setting concurrency level " + "to %d.", detected_cpus, detected_cpus); + } else +#else +#warning _SC_NPROCESSORS_ONLN not defined; nvidia-installer will not be able \ +to detect the number of processors. +#endif + { + ui_log(op, "Unable to detect the number of processors: setting " + "concurrency level to 1."); + detected_cpus = 1; + } + op->concurrency_level = detected_cpus; + } + + if (op->expert) { + int val = op->concurrency_level; + do { + char *strval = nvasprintf("%d", val); + val = atoi(ui_get_input(op, strval, "Concurrency level")); + nvfree(strval); + } while (val < 1); + op->concurrency_level = val; + } +} @@ -79,11 +79,10 @@ int tls_test(Options *op, int compat_32_libs); int check_runtime_configuration(Options *op, Package *p); void collapse_multiple_slashes(char *s); int is_symbolic_link_to(const char *path, const char *dest); -Distribution get_distribution(Options *op); int check_for_running_x(Options *op); -int check_for_modular_xorg(Options *op); +void query_xorg_version(Options *op); int check_for_nvidia_graphics_devices(Options *op, Package *p); -int run_nvidia_xconfig(Options *op, int restore); +int run_nvidia_xconfig(Options *op, int restore, const char *question, int answer); HookScriptStatus run_distro_hook(Options *op, const char *hook); int check_for_alternate_install(Options *op); int check_for_nouveau(Options *op); @@ -94,5 +93,6 @@ int verify_crc(Options *op, const char *filename, unsigned int crc, unsigned int *actual_crc); int secure_boot_enabled(void); ElfFileType get_elf_architecture(const char *filename); +void set_concurrency_level(Options *op); #endif /* __NVIDIA_INSTALLER_MISC_H__ */ diff --git a/ncurses-ui.c b/ncurses-ui.c index 621846e..e28f229 100644 --- a/ncurses-ui.c +++ b/ncurses-ui.c @@ -898,7 +898,7 @@ static void nv_ncurses_status_update(Options *op, const float percent, */ if (ch == NV_NCURSES_CTRL('L')) { nv_ncurses_check_resize(d, TRUE); - if (d->message) nv_ncurses_destroy_region(d->message); + nv_ncurses_destroy_region(d->message); nv_ncurses_do_progress_bar_region(d); } } diff --git a/nvidia-installer.c b/nvidia-installer.c index 2a45222..f243654 100644 --- a/nvidia-installer.c +++ b/nvidia-installer.c @@ -134,7 +134,6 @@ static Options *load_default_options(void) op->ftp_site = DEFAULT_FTP_SITE; op->tmpdir = get_tmpdir(op); - op->distro = get_distribution(op); op->logging = TRUE; /* log by default */ op->opengl_headers = FALSE; /* do not install our GL headers by default */ @@ -150,6 +149,7 @@ static Options *load_default_options(void) op->check_for_alternate_installs = TRUE; op->num_kernel_modules = 1; op->install_uvm = TRUE; + op->install_compat32_libs = NV_OPTIONAL_BOOL_DEFAULT; return op; @@ -206,7 +206,6 @@ static void parse_commandline(int argc, char *argv[], Options *op) op->driver_info = TRUE; op->ui_str = "none"; break; - case 'n': op->no_precompiled_interface = TRUE; break; case 'c': op->no_ncurses_color = TRUE; break; case 'l': op->latest = TRUE; break; @@ -230,12 +229,20 @@ static void parse_commandline(int argc, char *argv[], Options *op) break; case 'z': op->no_nouveau_check = TRUE; break; case 'Z': op->disable_nouveau = TRUE; break; - case 'k': op->kernel_name = strval; op->no_precompiled_interface = TRUE; op->ignore_cc_version_check = TRUE; break; + case 'j': + if (intval < 1) { + nv_error_msg("Invalid concurrency level %d: nvidia-installer " + "will attempt to autodetect the number of CPUs.", + intval); + intval = 0; + } + op->concurrency_level = intval; + break; case XFREE86_PREFIX_OPTION: case X_PREFIX_OPTION: @@ -244,6 +251,8 @@ static void parse_commandline(int argc, char *argv[], Options *op) op->x_library_path = strval; break; case X_MODULE_PATH_OPTION: op->x_module_path = strval; break; + case X_SYSCONFIG_PATH_OPTION: + op->x_sysconfig_path = strval; break; case OPENGL_PREFIX_OPTION: op->opengl_prefix = strval; break; case OPENGL_LIBDIR_OPTION: @@ -255,6 +264,10 @@ static void parse_commandline(int argc, char *argv[], Options *op) op->compat32_prefix = strval; break; case COMPAT32_LIBDIR_OPTION: op->compat32_libdir = strval; break; + case INSTALL_COMPAT32_LIBS_OPTION: + op->install_compat32_libs = boolval ? NV_OPTIONAL_BOOL_TRUE : + NV_OPTIONAL_BOOL_FALSE; + break; #endif case DOCUMENTATION_PREFIX_OPTION: op->documentation_prefix = strval; break; @@ -276,6 +289,8 @@ static void parse_commandline(int argc, char *argv[], Options *op) op->kernel_module_installation_path = strval; break; case UNINSTALL_OPTION: op->uninstall = TRUE; break; + case SKIP_MODULE_UNLOAD_OPTION: + op->skip_module_unload = TRUE; break; case PROC_MOUNT_POINT_OPTION: op->proc_mount_point = strval; break; case USER_INTERFACE_OPTION: @@ -291,6 +306,7 @@ static void parse_commandline(int argc, char *argv[], Options *op) op->opengl_headers = TRUE; break; case NO_NVIDIA_MODPROBE_OPTION: op->nvidia_modprobe = FALSE; break; +#if defined(NV_TLS_TEST) case FORCE_TLS_OPTION: if (strcasecmp(strval, "new") == 0) op->which_tls = FORCE_NEW_TLS; @@ -312,7 +328,8 @@ static void parse_commandline(int argc, char *argv[], Options *op) goto fail; } break; -#endif +#endif /* NV_X86_64 */ +#endif /* NV_TLS_TEST */ case SANITY_OPTION: op->sanity = TRUE; break; @@ -555,6 +572,11 @@ int main(int argc, char *argv[]) /* initialize the user interface */ if (!ui_init(op)) return 1; + + /* determine the concurrency level: do this early on, to allow for + * parallelization of as much of the install as possible. */ + + set_concurrency_level(op); /* check that we're running as root */ @@ -571,11 +593,10 @@ int main(int argc, char *argv[]) if (!find_module_utils(op)) goto done; if (!check_selinux(op)) goto done; - /* check if we need to worry about modular Xorg */ + /* check for X server properties based on the version of the server */ + + query_xorg_version(op); - op->modular_xorg = - check_for_modular_xorg(op); - /* get the default installation prefixes/paths */ get_default_prefixes_and_paths(op); diff --git a/nvidia-installer.h b/nvidia-installer.h index fdb1ddf..eed02a7 100644 --- a/nvidia-installer.h +++ b/nvidia-installer.h @@ -57,6 +57,7 @@ typedef enum { PKG_CONFIG, XSERVER, OPENSSL, + DKMS, MAX_SYSTEM_OPTIONAL_UTILS } SystemOptionalUtils; @@ -92,22 +93,6 @@ typedef enum { #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. - */ - -typedef enum { - SUSE, - UNITED_LINUX, - DEBIAN, - UBUNTU, - GENTOO, - ARCH, - OTHER -} Distribution; - typedef uint32_t uint32; typedef uint16_t uint16; @@ -128,6 +113,7 @@ typedef struct __options { int update; int expert; int uninstall; + int skip_module_unload; int driver_info; int debug; int logging; @@ -139,8 +125,10 @@ typedef struct __options { int nvidia_modprobe; int no_questions; int silent; +#if defined(NV_TLS_TEST) int which_tls; int which_tls_compat32; +#endif /* NV_TLS_TEST */ int sanity; int add_this_kernel; int no_backup; @@ -167,8 +155,12 @@ typedef struct __options { int num_kernel_modules; int install_uvm; int uvm_files_packaged; + int compat32_files_packaged; + int x_files_packaged; + int concurrency_level; NVOptionalBool install_vdpau_wrapper; + NVOptionalBool install_compat32_libs; char *opengl_prefix; char *opengl_libdir; @@ -179,6 +171,7 @@ typedef struct __options { char *x_moddir; char *x_module_path; char *x_library_path; + char *x_sysconfig_path; char *compat32_chroot; char *compat32_prefix; @@ -198,6 +191,7 @@ typedef struct __options { char *application_profile_path; int modular_xorg; + int xorg_supports_output_class; char *kernel_source_path; char *kernel_output_path; @@ -231,8 +225,6 @@ typedef struct __options { int kernel_module_signed; - Distribution distro; - void *ui_priv; /* for use by the ui's */ int ignore_cc_version_check; @@ -249,11 +241,8 @@ typedef enum { FILE_TYPE_KERNEL_MODULE_CMD, FILE_TYPE_OPENGL_HEADER, FILE_TYPE_OPENGL_LIB, - FILE_TYPE_XLIB_STATIC_LIB, - FILE_TYPE_XLIB_SHARED_LIB, FILE_TYPE_DOCUMENTATION, FILE_TYPE_OPENGL_SYMLINK, - FILE_TYPE_XLIB_SYMLINK, FILE_TYPE_KERNEL_MODULE, FILE_TYPE_INSTALLER_BINARY, FILE_TYPE_UTILITY_BINARY, @@ -269,7 +258,11 @@ typedef enum { FILE_TYPE_MANPAGE, FILE_TYPE_EXPLICIT_PATH, FILE_TYPE_CUDA_LIB, + FILE_TYPE_OPENCL_LIB, + FILE_TYPE_OPENCL_WRAPPER_LIB, FILE_TYPE_CUDA_SYMLINK, + FILE_TYPE_OPENCL_LIB_SYMLINK, + FILE_TYPE_OPENCL_WRAPPER_SYMLINK, FILE_TYPE_VDPAU_LIB, FILE_TYPE_VDPAU_WRAPPER_LIB, FILE_TYPE_VDPAU_SYMLINK, @@ -291,6 +284,7 @@ typedef enum { FILE_TYPE_NVIFR_LIB, FILE_TYPE_NVIFR_LIB_SYMLINK, FILE_TYPE_UVM_MODULE_SRC, + FILE_TYPE_XORG_OUTPUTCLASS_CONFIG, FILE_TYPE_MAX } PackageEntryFileType; @@ -315,6 +309,7 @@ typedef struct { unsigned int is_shared_lib : 1; unsigned int is_opengl : 1; unsigned int is_temporary : 1; + unsigned int is_wrapper : 1; } PackageEntryFileCapabilities; /* @@ -374,6 +369,25 @@ typedef struct __package_entry { */ } PackageEntry; +/* + * Information about a conflicting file; nvidia-installer searches for existing + * files that conflict with files that are to be installed. + */ + +typedef struct { + const char *name; + int len; + + /* + * if requiredString is non-NULL, then a file must have this + * string in order to be considered a conflicting file; we use + * this to only consider "libglx.*" files conflicts if they have + * the string "glxModuleData". + */ + + const char *requiredString; +} ConflictingFileInfo; + typedef struct __package { @@ -397,6 +411,7 @@ typedef struct __package { PackageEntry *entries; /* array of filename/checksum/bytesize entries */ int num_entries; + ConflictingFileInfo *conflicting_files; } Package; @@ -439,16 +454,25 @@ typedef struct __package { #define DEFAULT_APPLICATION_PROFILE_PATH "/usr/share/nvidia" #define DEFAULT_LIBDIR "lib" +#define DEFAULT_32BIT_LIBDIR "lib32" #define DEFAULT_64BIT_LIBDIR "lib64" +#define DEFAULT_IA32_TRIPLET_LIBDIR "lib/i386-linux-gnu" +#define DEFAULT_AMD64_TRIPLET_LIBDIR "lib/x86_64-linux-gnu" +#define DEFAULT_ARMV7_TRIPLET_LIBDIR "lib/arm-linux-gnueabi" +#define DEFAULT_ARMV7HF_TRIPLET_LIBDIR "lib/arm-linux-gnueabihf" +#define DEFAULT_AARCH64_TRIPLET_LIBDIR "lib/aarch64-linux-gnu" +#define DEFAULT_PPC64LE_TRIPLET_LIBDIR "lib/powerpc64le-linux-gnu" #define DEFAULT_BINDIR "bin" #define DEFAULT_INCDIR "include" #define DEFAULT_X_MODULEDIR "modules" #define DEFAULT_DOT_DESKTOPDIR "share/applications" #define DEFAULT_DOCDIR "share/doc" #define DEFAULT_MANDIR "share/man" +#define DEFAULT_CONFDIR "X11/xorg.conf.d" #define DEFAULT_MODULE_SIGNING_KEY_PATH "/usr/share/nvidia" #define DEFAULT_KERNEL_MODULE_SRC_PREFIX "/usr/src" +#define DEFAULT_X_DATAROOT_PATH "/usr/share" /* * As of Xorg 7.x, X components need not be installed relative @@ -467,29 +491,6 @@ typedef struct __package { */ #define DEBIAN_DEFAULT_COMPAT32_CHROOT "/emul/ia32-linux" -/* - * Debian GNU/Linux and Ubuntu do not follow the lib64 library - * path naming convention used by other distributors. 64-bit - * libraries are placed under ../lib. - */ -#define DEBIAN_DEFAULT_64BIT_LIBDIR "lib" - -/* - * Ubuntu GNU/Linux and Gentoo Linux do not follow the "lib" - * library path naming convention used for 32-bit compatibility - * libraries by other distributors. These libraries are - * placed under ../lib32. - */ -#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" #define DEFAULT_FTP_SITE "ftp://download.nvidia.com" diff --git a/option_table.h b/option_table.h index 1d49dda..c9c5c60 100644 --- a/option_table.h +++ b/option_table.h @@ -41,6 +41,7 @@ enum { KERNEL_INCLUDE_PATH_OPTION, KERNEL_INSTALL_PATH_OPTION, UNINSTALL_OPTION, + SKIP_MODULE_UNLOAD_OPTION, PROC_MOUNT_POINT_OPTION, USER_INTERFACE_OPTION, LOG_FILE_NAME_OPTION, @@ -96,6 +97,8 @@ enum { NO_CHECK_FOR_ALTERNATE_INSTALLS_OPTION, MULTIPLE_KERNEL_MODULES_OPTION, NO_UVM_OPTION, + INSTALL_COMPAT32_LIBS_OPTION, + X_SYSCONFIG_PATH_OPTION, }; static const NVGetoptOption __options[] = { @@ -138,6 +141,11 @@ static const NVGetoptOption __options[] = { { "uninstall", UNINSTALL_OPTION, 0, NULL, "Uninstall the currently installed NVIDIA driver." }, + { "skip-module-unload", SKIP_MODULE_UNLOAD_OPTION, + NVGETOPT_OPTION_APPLIES_TO_NVIDIA_UNINSTALL, NULL, + "When uninstalling the driver, skip unloading of the NVIDIA kernel " + "module. This option is ignored when the driver is being installed." }, + { "sanity", SANITY_OPTION, 0, NULL, "Perform basic sanity tests on an existing NVIDIA " "driver installation." }, @@ -192,6 +200,13 @@ static const NVGetoptOption __options[] = { DEFAULT_64BIT_LIBDIR "' or '" DEFAULT_LIBDIR "' on 64bit systems, " "depending on the installed Linux distribution." }, + { "x-sysconfig-path", X_SYSCONFIG_PATH_OPTION, NVGETOPT_STRING_ARGUMENT, NULL, + "The path under which X system configuration files will be installed. " + "If this option is not specified, nvidia-installer uses the following " + "search order and selects the first valid directory it finds: 1) " + "`pkg-config --variable=sysconfigdir xorg-server`, or 2) " + DEFAULT_X_DATAROOT_PATH "/" DEFAULT_CONFDIR "." }, + { "opengl-prefix", OPENGL_PREFIX_OPTION, NVGETOPT_STRING_ARGUMENT, NULL, "The prefix under which the OpenGL components of the " "NVIDIA driver will be installed; the default is: '" DEFAULT_OPENGL_PREFIX @@ -229,9 +244,16 @@ static const NVGetoptOption __options[] = { "The path relative to the 32bit compatibility prefix under which the " "32bit compatibility components of the NVIDIA driver will " "be installed. The default is '" DEFAULT_LIBDIR "' or '" - UBUNTU_DEFAULT_COMPAT32_LIBDIR "', depending on the installed Linux " + DEFAULT_32BIT_LIBDIR "', depending on the installed Linux " "distribution. Only under very rare circumstances should this " "option be used." }, + + { "install-compat32-libs", INSTALL_COMPAT32_LIBS_OPTION, + NVGETOPT_IS_BOOLEAN, NULL, + "32-bit compatibility libraries may be optionally installed. Setting " + "--install-compat32-libs will install these libraries. Setting " + "--no-install-compat32-libs will skip installation of these libraries. " + "Note: this option will have no effect on -no-compat32.run packages." }, #endif /* NV_X86_64 */ { "installer-prefix", INSTALLER_PREFIX_OPTION, NVGETOPT_STRING_ARGUMENT, @@ -366,6 +388,7 @@ static const NVGetoptOption __options[] = { "needed if other means of loading the NVIDIA kernel module and creating " "the NVIDIA device files are unavailable." }, +#if defined(NV_TLS_TEST) { "force-tls", FORCE_TLS_OPTION, NVGETOPT_STRING_ARGUMENT, NULL, "NVIDIA's OpenGL libraries are compiled with one of two " "different thread local storage (TLS) mechanisms: 'classic tls' " @@ -383,6 +406,7 @@ static const NVGetoptOption __options[] = { "32bit compatibility OpenGL TLS library; further details " "can be found in the description of the '--force-tls' option." }, #endif /* NV_X86_64 */ +#endif { "kernel-name", 'k', NVGETOPT_STRING_ARGUMENT, NULL, "Build and install the NVIDIA kernel module for the " @@ -620,16 +644,22 @@ static const NVGetoptOption __options[] = { NVGETOPT_INTEGER_ARGUMENT, NULL, "Build and install multiple NVIDIA kernel modules. The maximum number " "of NVIDIA kernel modules that may be built is 8. '--multiple-kernel-" - "modules' implies '--no-unified-memory'."}, + "modules' implies '--no-unified-memory'." }, { "no-unified-memory", NO_UVM_OPTION, 0, NULL, "Do not install the NVIDIA Unified Memory kernel module. This kernel " - "module is required for CUDA, and if it is not installed, the CUDA " - "driver and CUDA applications will not be able to run. The " - "'--no-unified-memory' option should only be used to work around " - "failures to build or install the Unified Memory kernel module on " + "module is required for CUDA on 64-bit systems, and if it is not " + "installed, the CUDA driver and CUDA applications will not be able to " + "run. The '--no-unified-memory' option should only be used to work " + "around failures to build or install the Unified Memory kernel module on " "systems that do not need to run CUDA." }, + { "concurrency-level", 'j', NVGETOPT_INTEGER_ARGUMENT, NULL, + "Set the concurrency level for operations such as building the kernel " + "module which may be parallelized on SMP systems. By default, this will " + "be set to the number of detected CPUs, or to '1', if nvidia-installer " + "fails to detect the number of CPUs." }, + /* Orphaned options: These options were in the long_options table in * nvidia-installer.c but not in the help. */ { "debug", 'd', 0, NULL,NULL }, diff --git a/precompiled.c b/precompiled.c index 5a4c1c1..50d6183 100644 --- a/precompiled.c +++ b/precompiled.c @@ -81,7 +81,7 @@ static uint32 read_uint32(const char *buf, int *offset) char *read_proc_version(Options *op, const char *proc_mount_point) { - int fd, ret, len, version_len; + int fd, len, version_len; char *version, *c = NULL; char *proc_verson_filename; @@ -105,6 +105,8 @@ char *read_proc_version(Options *op, const char *proc_mount_point) version = NULL; while (1) { + int ret; + if (version_len == len) { version_len += NV_LINE_LEN; version = nvrealloc(version, version_len); @@ -114,8 +116,9 @@ char *read_proc_version(Options *op, const char *proc_mount_point) if (ret == -1) { ui_warn(op, "Error reading %s (%s).", proc_verson_filename, strerror(errno)); - free(version); - return NULL; + nvfree(version); + version = NULL; + goto done; } if (ret == 0) { *c = '\0'; @@ -131,11 +134,12 @@ char *read_proc_version(Options *op, const char *proc_mount_point) while ((*c != '\0') && (*c != '\n')) c++; *c = '\0'; - free(proc_verson_filename); + done: + nvfree(proc_verson_filename); + close(fd); return version; - -} /* read_proc_version() */ +} @@ -160,7 +164,7 @@ PrecompiledInfo *get_precompiled_info(Options *op, PrecompiledFileInfo *fileInfos = NULL; fd = size = 0; - buf = description = proc_version_string = NULL; + buf = description = proc_version_string = version = NULL; /* open the file to be unpacked */ @@ -233,7 +237,7 @@ PrecompiledInfo *get_precompiled_info(Options *op, /* check if this precompiled kernel interface is the right driver version */ - if (package_version && (strcmp(version, package_version) != 0)) { + if (!version || !package_version || strcmp(version, package_version) != 0) { goto done; } @@ -332,11 +336,11 @@ PrecompiledInfo *get_precompiled_info(Options *op, info->files = fileInfos; /* - * XXX so that the proc version and description strings, and the + * XXX so that the proc version, description, and version strings, and the * PrecompiledFileInfo array aren't freed below */ - proc_version_string = description = NULL; + proc_version_string = description = version = NULL; fileInfos = NULL; done: @@ -344,10 +348,11 @@ done: /* cleanup whatever needs cleaning up */ if (buf) munmap(buf, size); - if (fd > 0) close(fd); - if (description) free(description); - if (proc_version_string) free(proc_version_string); - if (fileInfos) free(fileInfos); + if (fd >= 0) close(fd); + nvfree(description); + nvfree(proc_version_string); + nvfree(fileInfos); + nvfree(version); return info; @@ -942,11 +947,17 @@ const char **precompiled_file_attribute_names(uint32 attribute_mask) "linked module crc", "embedded signature", }; + static const char *unknown_attribute = "unknown attribute"; - ret = nvalloc((ARRAY_LEN(file_attribute_names) + 1) * sizeof(char *)); + const int max_file_attribute_names = sizeof(attribute_mask) * 8; - for (i = 0; i < 32; i++) { - if (attribute_mask & (1 << i)) { + /* leave room for a NULL terminator */ + ret = nvalloc((max_file_attribute_names + 1) * sizeof(char *)); + + for (i = 0; i < max_file_attribute_names; i++) { + if (i >= ARRAY_LEN(file_attribute_names)) { + ret[attr++] = unknown_attribute; + } else if (attribute_mask & (1 << i)) { ret[attr++] = file_attribute_names[i]; } } @@ -997,6 +1008,8 @@ int byte_tail(const char *infile, int start, char **buf) } done: - fclose(in); + if (in) { + fclose(in); + } return size; } @@ -21,18 +21,10 @@ */ #include "nvidia-installer.h" -#include "command-list.h" #include "user-interface.h" #include "backup.h" -#include "misc.h" #include "sanity.h" -#include <sys/types.h> -#include <sys/shm.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - /* * sanity() - perform sanity tests on an existing installation @@ -68,10 +60,6 @@ int sanity(Options *op) return FALSE; } - /* check that shared memory works */ - - if (!check_sysvipc(op)) return FALSE; - /* * XXX There are lots of additional tests that could be added: * @@ -95,39 +83,3 @@ int sanity(Options *op) return TRUE; } /* sanity() */ - - -/* - * check_sysvipc() - test that shmat() and friends work - */ - -int check_sysvipc(Options *op) -{ - int shmid = -1; - int ret = FALSE; - int size = sysconf(_SC_PAGESIZE); - void *address = (void *) -1; - - shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); - if (shmid == -1) goto done; - - address = shmat(shmid, 0, 0); - if (address == (void *) -1) goto done; - - ret = TRUE; - - done: - - if (shmid != -1) shmctl(shmid, IPC_RMID, 0); - if (address != (void *) -1) shmdt(address); - - if (ret) { - ui_log(op, "Shared memory test passed."); - } else { - ui_message(op, "Shared memory test failed (%s): please check that " - "your kernel has CONFIG_SYSVIPC enabled.", strerror(errno)); - } - - return ret; - -} /* check_sysvipc() */ @@ -24,6 +24,5 @@ #define __NVIDIA_INSTALLER_SANITY_H__ int sanity(Options *); -int check_sysvipc(Options *op); #endif /* __NVIDIA_INSTALLER_SANITY_H__ */ diff --git a/snarf-ftp.c b/snarf-ftp.c index d2cde60..4a2d171 100644 --- a/snarf-ftp.c +++ b/snarf-ftp.c @@ -317,8 +317,8 @@ int ftp_transfer(UrlResource *rsrc) /* do the password dance */ if (!check_numeric("230", line)) { if (!check_numeric("331", line)) { - nvfree(line); ui_error(rsrc->op, "bad/unexpected response: %s", line); + nvfree(line); return FALSE; } else { nvfree(line); diff --git a/tls_test_Linux-ia64 b/tls_test_Linux-ia64 Binary files differdeleted file mode 100755 index 23a50b7..0000000 --- a/tls_test_Linux-ia64 +++ /dev/null diff --git a/tls_test_dso_Linux-ia64.so b/tls_test_dso_Linux-ia64.so Binary files differdeleted file mode 100755 index b1ac50f..0000000 --- a/tls_test_dso_Linux-ia64.so +++ /dev/null @@ -265,11 +265,11 @@ static int get_latest_driver_version_and_filename(Options *op, char **pFileName) { int fd = -1; - int length; + int length = 0; int ret = FALSE; char *tmpfile = NULL; char *url = NULL; - char *str = (void *) -1; + char *str = MAP_FAILED; char *s = NULL; char *buf = NULL; char *buf2 = NULL; @@ -311,7 +311,7 @@ static int get_latest_driver_version_and_filename(Options *op, length = stat_buf.st_size; str = mmap(0, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0); - if (str == (void *) -1) { + if (str == MAP_FAILED) { ui_error(op, "Unable to determine most recent NVIDIA %s-%s driver " "version (%s).", INSTALLER_OS, INSTALLER_ARCH, strerror(errno)); @@ -354,7 +354,7 @@ static int get_latest_driver_version_and_filename(Options *op, nvfree(buf); nvfree(buf2); - if (str != (void *) -1) munmap(str, stat_buf.st_size); + if (str != MAP_FAILED) munmap(str, length); if (fd != -1) close(fd); unlink(tmpfile); @@ -364,5 +364,4 @@ static int get_latest_driver_version_and_filename(Options *op, nvfree(version); return ret; - -} /* get_latest_driver_version() */ +} diff --git a/user-interface.c b/user-interface.c index 8009672..adf9ca1 100644 --- a/user-interface.c +++ b/user-interface.c @@ -126,7 +126,7 @@ int ui_init(Options *op) i = 1; } - for (; ui_list[i].descr && !__ui; i++) { + for (; i < ARRAY_LEN(ui_list) && ui_list[i].descr && !__ui; i++) { if (!extract_user_interface(op, &ui_list[i])) continue; @@ -605,7 +605,7 @@ static int extract_user_interface(Options *op, user_interface_attribute_t *ui) if (dst != (void *) -1) munmap(dst, ui->data_array_size); if (fd != -1) { close(fd); unlink(ui->filename); } - if (ui->filename) free(ui->filename); + free(ui->filename); return FALSE; @@ -55,6 +55,7 @@ endif INSTALL ?= install INSTALL_BIN_ARGS ?= -m 755 +INSTALL_LIB_ARGS ?= -m 644 INSTALL_DOC_ARGS ?= -m 644 M4 ?= m4 @@ -98,6 +99,26 @@ ifndef TARGET_ARCH TARGET_ARCH := $(subst i686,x86,$(TARGET_ARCH)) endif +ifeq ($(TARGET_ARCH),x86) + CFLAGS += -DNV_X86 -DNV_ARCH_BITS=32 +endif + +ifeq ($(TARGET_ARCH),x86_64) + CFLAGS += -DNV_X86_64 -DNV_ARCH_BITS=64 +endif + +ifeq ($(TARGET_ARCH),armv7l) + CFLAGS += -DNV_ARMV7 -DNV_ARCH_BITS=32 +endif + +ifeq ($(TARGET_ARCH),aarch64) + CFLAGS += -DNV_AARCH64 -DNV_ARCH_BITS=64 +endif + +ifeq ($(TARGET_ARCH),ppc64le) + CFLAGS += -DNV_PPC64LE -DNV_ARCH_BITS=64 +endif + ifeq ($(TARGET_OS),Linux) LIBDL_LIBS = -ldl else @@ -113,6 +134,14 @@ ifeq ($(TARGET_ARCH),armv7l) endif TARGET_ARCH_ABI ?= +ifeq ($(TARGET_ARCH_ABI),gnueabi) + CFLAGS += -DNV_GNUEABI +endif + +ifeq ($(TARGET_ARCH_ABI),gnueabihf) + CFLAGS += -DNV_GNUEABIHF +endif + OUTPUTDIR ?= _out/$(TARGET_OS)_$(TARGET_ARCH) OUTPUTDIR_ABSOLUTE ?= $(CURDIR)/$(OUTPUTDIR) @@ -143,6 +172,7 @@ endif PREFIX ?= /usr/local BINDIR = $(DESTDIR)$(PREFIX)/bin +LIBDIR = $(DESTDIR)$(PREFIX)/lib MANDIR = $(DESTDIR)$(PREFIX)/share/man/man1 @@ -230,7 +260,7 @@ NV_MODULE_LOGGING_NAME ?= ifeq ($(NV_VERBOSE),0) quiet_cmd = @$(PRINTF) \ - " $(if $(NV_MODULE_LOGGING_NAME),[ %-17.17s ],%s) $(quiet_$(1))\n" \ + " $(if $(NV_MODULE_LOGGING_NAME),[ %-17.17s ],%s) $(quiet_$(1))\n" \ "$(NV_MODULE_LOGGING_NAME)" && $($(1)) else quiet_cmd = $($(1)) @@ -262,32 +292,49 @@ quiet_STRIP_CMD = $(call define_quiet_cmd,STRIP ,$@) ############################################################################## # function to generate a list of object files from their corresponding -# source files; example usage: +# source files using the specified path. The _WITH_DIR variant takes an +# output path as the second argument while the BUILD_OBJECT_LIST defaults +# to using the value of OUTPUTDIR as the output path. example usage: # -# OBJS = $(call BUILD_OBJECT_LIST,$(SRC)) +# OBJS = $(call BUILD_OBJECT_LIST_WITH_DIR,$(SRC),$(DIR)) ############################################################################## +BUILD_OBJECT_LIST_WITH_DIR = \ + $(addprefix $(2)/,$(notdir $(addsuffix .o,$(basename $(1))))) + BUILD_OBJECT_LIST = \ - $(addprefix $(OUTPUTDIR)/,$(notdir $(addsuffix .o,$(basename $(1))))) + $(call BUILD_OBJECT_LIST_WITH_DIR,$(1),$(OUTPUTDIR)) ############################################################################## # function to generate a list of dependency files from their -# corresponding source files; example usage: +# corresponding source files using the specified path. The _WITH_DIR +# variant takes an output path as the second argument while the +# BUILD_DEPENDENCY_LIST default to using the value of OUTPUTDIR as the +# output path. example usage: # -# DEPS = $(call BUILD_DEPENDENCY_LIST,$(SRC)) +# DEPS = $(call BUILD_DEPENDENCY_LIST_WITH_DIR,$(SRC),$(DIR)) ############################################################################## +BUILD_DEPENDENCY_LIST_WITH_DIR = \ + $(addprefix $(2)/,$(notdir $(addsuffix .d,$(basename $(1))))) + BUILD_DEPENDENCY_LIST = \ - $(addprefix $(OUTPUTDIR)/,$(notdir $(addsuffix .d,$(basename $(1))))) + $(call BUILD_DEPENDENCY_LIST_WITH_DIR,$(1),$(OUTPUTDIR)) ############################################################################## # functions to define a rule to build an object file; the first -# argument whether the rule is for the target or host platform ("HOST" -# or "TARGET"), the second argument is the source file to compile, and -# the third argument (_WITH_OBJECT_NAME-only) is the object filename -# to produce. Example usage: +# argument for all functions is whether the rule is for the target or +# host platform ("HOST" or "TARGET"), the second argument for all +# functions is the source file to compile. +# +# The _WITH_OBJECT_NAME and _WITH_DIR function name suffixes describe +# the third and possibly fourth arguments based on order. The +# _WITH_OBJECT_NAME argument is the object filename to produce while +# the _WITH_DIR argument is the destination path for the object file. +# +# Example usage: # # $(eval $(call DEFINE_OBJECT_RULE,TARGET,foo.c)) # @@ -299,26 +346,35 @@ BUILD_DEPENDENCY_LIST = \ # from the source file name (this is normally what you want). ############################################################################## -define DEFINE_OBJECT_RULE_WITH_OBJECT_NAME +define DEFINE_OBJECT_RULE_WITH_OBJECT_NAME_WITH_DIR $(3): $(2) - @$(MKDIR) $(OUTPUTDIR) + @$(MKDIR) $(4) $$(call quiet_cmd,$(call host_target_cc,$(1))) \ $$($(call host_target_cflags,$(1))) -c $$< -o $$@ \ $(call AUTO_DEP_CMD,$(1),$(2),$(3)) - -include $$(call BUILD_DEPENDENCY_LIST,$(3)) + -include $$(call BUILD_DEPENDENCY_LIST_WITH_DIR,$(3),$(4)) # declare empty rule for generating dependency file; we generate the # dependency files implicitly when compiling the source file (see # AUTO_DEP_CMD above), so we don't want gmake to spend time searching # for an explicit rule to generate the dependency file - $$(call BUILD_DEPENDENCY_LIST,$(3)): ; + $$(call BUILD_DEPENDENCY_LIST_WITH_DIR,$(3),$(4)): ; + +endef + +define DEFINE_OBJECT_RULE_WITH_OBJECT_NAME + $$(eval $$(call DEFINE_OBJECT_RULE_WITH_OBJECT_NAME_WITH_DIR,$(1),$(2),\ + $(3),$(OUTPUTDIR))) +endef +define DEFINE_OBJECT_RULE_WITH_DIR + $$(eval $$(call DEFINE_OBJECT_RULE_WITH_OBJECT_NAME_WITH_DIR,$(1),$(2),\ + $$(call BUILD_OBJECT_LIST_WITH_DIR,$(2),$(3)),$(3))) endef define DEFINE_OBJECT_RULE - $$(eval $$(call DEFINE_OBJECT_RULE_WITH_OBJECT_NAME,$(1),$(2),\ - $$(call BUILD_OBJECT_LIST,$(2)))) + $$(eval $$(call DEFINE_OBJECT_RULE_WITH_DIR,$(1),$(2),$(OUTPUTDIR))) endef @@ -1 +1 @@ -NVIDIA_VERSION = 343.22 +NVIDIA_VERSION = 346.16 |