summaryrefslogtreecommitdiff
path: root/sanity.c
diff options
context:
space:
mode:
Diffstat (limited to 'sanity.c')
-rw-r--r--sanity.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/sanity.c b/sanity.c
new file mode 100644
index 0000000..c5527d3
--- /dev/null
+++ b/sanity.c
@@ -0,0 +1,305 @@
+/*
+ * nvidia-installer: A tool for installing NVIDIA software packages on
+ * Unix and Linux systems.
+ *
+ * Copyright (C) 2003 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * sanity.c
+ */
+
+#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
+ */
+
+int sanity(Options *op)
+{
+ char *descr;
+ int major, minor, patch;
+
+ /* check that there's a driver installed at all */
+
+ descr = get_installed_driver_version_and_descr(op, &major, &minor, &patch);
+
+ if (!descr) {
+ ui_error(op, "Unable to find any installed NVIDIA driver. The sanity "
+ "check feature is only intended to be used with an existing "
+ "NVIDIA driver installation.");
+ return FALSE;
+ }
+
+ ui_message(op, "The currently installed driver is: '%s' "
+ "(version: %d.%d-%d). nvidia-installer will now check "
+ "that all installed files still exist.",
+ descr, major, minor, patch);
+
+ /* check that all the files are still where we placed them */
+
+ if (!test_installed_files(op)) {
+ ui_message(op, "The '%s' installation has been altered "
+ "since it was originally installed. It is recommended "
+ "that you reinstall.", descr);
+ return FALSE;
+ }
+
+ /* check that shared memory works */
+
+ if (!check_sysvipc(op)) return FALSE;
+
+ /*
+ * XXX There are lots of additional tests that could be added:
+ *
+ * - check for any conflicting libraries
+ *
+ * - check that the permissions on the /dev/nvidia* files haven't
+ * been screwed up by pam
+ *
+ * - check that /dev/zero has appropriate permissions
+ *
+ * - check for possible kernel config problems (IPC, mtrr support,
+ * etc).
+ */
+
+ ui_message(op, "'%s' (version: %d.%d-%d) appears to be installed "
+ "correctly.", descr, major, minor, patch);
+
+ nvfree(descr);
+
+ 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() */
+
+
+#if 0
+
+
+/*
+ * XXX don't have time to finish implementing and testing this right
+ * now...
+ */
+
+
+
+
+/*
+ * find_conflicting_libraries() -
+ */
+
+static int find_conflicting_libraries(Options *op)
+{
+ FileList *l;
+ struct stat stat_buf;
+ int i;
+
+ l = (FileList *) nvalloc(sizeof(FileList));
+
+ /* search for possibly conflicting libraries */
+
+ find_conflicting_xfree86_libraries(DEFAULT_XFREE86_INSTALLATION_PREFIX, l);
+
+ if (strcmp(DEFAULT_XFREE86_INSTALLATION_PREFIX, op->xfree86_prefix) != 0)
+ find_conflicting_xfree86_libraries(op->xfree86_prefix, l);
+
+ find_conflicting_opengl_libraries(DEFAULT_OPENGL_INSTALLATION_PREFIX, l);
+
+ if (strcmp(DEFAULT_OPENGL_INSTALLATION_PREFIX, op->opengl_prefix) != 0)
+ find_conflicting_opengl_libraries(op->opengl_prefix, l);
+
+ /* condense the file list */
+
+ condense_file_list(l);
+
+ /* for each file in the list, check if it's an NVIDIA file */
+
+ for (i = 0; i < l->num; i++) {
+ if (lstat(l->filename[i], &stat_buf) == -1) {
+ ui_error(op, "Unable to determine properties for file '%s' (%s).",
+ l->filename[i], strerror(errno));
+ continue;
+ }
+
+ if (S_ISREG(stat_buf.st_mode)) {
+ ret = is_nvidia_library(op, l->filename[i]);
+ } else if (S_ISLNK(stat_buf.st_mode)) {
+ ret = is_nvidia_symlink(op, l->filename[i]);
+ }
+ }
+
+
+
+
+ /* free the FileList */
+
+ for (i = 0; i < l->num; i++) free(l->filename[i]);
+ free(l->filename);
+ free(l);
+
+} /* find_conflicting_libraries() */
+
+
+
+/*
+ * is_nvidia_library() - mmap the file and scan through it for the
+ * nvidia string.
+ */
+
+static int is_nvidia_library(Options *op, const char *filename)
+{
+ int fd = -1, ret = FALSE;
+ struct stat stat_buf;
+ char *buf = (void *) -1, char *found;
+
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ ui_error(op, "Unable to open '%s' for reading (%s)",
+ filename, strerror(errno));
+ goto done:
+ }
+
+ if (fstat(fd, &stat_buf) == -1) {
+ ui_error(op, "Unable to determine size of '%s' (%s)",
+ filename, strerror(errno));
+ goto done;
+ }
+
+ if ((buf = mmap(0, stat_buf.st_size, PROT_READ,
+ MAP_FILE | MAP_SHARED, fd, 0)) == (void *) -1) {
+ ui_error(op, "Unable to map file '%s' for reading (%s)",
+ filename, strerror(errno));
+ goto done;
+ }
+
+ found = strstr(buf, "nvidia id: ");
+
+ if (found) ret = TRUE;
+
+ done:
+
+ if (buf != (void *) -1) munmap(buf, stat_buf.st_size);
+ if (fd != -1) close(fd);
+
+ return ret;
+
+} /* is_nvidia_library() */
+
+
+/*
+ * is_nvidia_symlink() - returns TRUE if this symlink should be moved
+ * out of the way. Find the target of the symlink, and recursively
+ * call is_nvidia_symlink() if the target is a symlink, or call
+ * is_nvidia_library() if the target is a regular file.
+ *
+ * XXX do we need to do anything about cyclic links?
+ */
+
+static int is_nvidia_symlink(Options *op, const char *filename)
+{
+ char *tmp, *tmp2, *dir, *target;
+ int ret = TRUE;
+ struct stat stat_buf;
+
+ tmp = get_symlink_target(op, filename);
+ if (!tmp) return FALSE;
+
+ /*
+ * prepend the basename of the file, unless the target is an
+ * abosolute path
+ */
+
+ if (tmp[0] != '/') {
+ tmp2 = nvstrdup(tmp);
+ dir = dirname(tmp2);
+ target = nvstrcat(dir, "/", tmp, NULL);
+ nvfree(tmp);
+ nvfree(tmp2);
+ } else {
+ target = tmp;
+ }
+
+
+ if (lstat(target, &stat_buf) == -1) {
+ ui_error(op, "Unable to determine properties for file '%s' (%s).",
+ target, strerror(errno));
+ return TRUE; /* return TRUE so that we don't try to back it up */
+ }
+
+ if (S_ISREG(stat_buf.st_mode)) {
+ ret = is_nvidia_library(op, target);
+ } else if (S_ISLNK(stat_buf.st_mode)) {
+ ret = is_nvidia_symlink(op, target);
+ }
+
+ nvfree(target);
+
+ return ret;
+
+} /* is_nvidia_symlink() */
+
+
+#endif