summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2008-02-13 10:20:38 -0800
committerAaron Plattner <aplattner@nvidia.com>2008-02-13 10:20:38 -0800
commit4d3c391aebad3c67ef9e77eba3fe86acc79541f5 (patch)
tree36bca53f74716b5bd9c474c0ef933006faf1a2bb
parent184ddefeab802bc3b119c49dede0d49fc5e01670 (diff)
100.14.03100.14.03
-rw-r--r--DRIVER_VERSION2
-rw-r--r--backup.c239
-rw-r--r--backup.h3
-rw-r--r--command-list.c35
-rw-r--r--files.c214
-rw-r--r--install-from-cwd.c133
-rw-r--r--kernel.c58
-rw-r--r--kernel.h1
-rw-r--r--misc.c222
-rw-r--r--misc.h2
-rw-r--r--mkprecompiled.c87
-rw-r--r--nvLegacy.h2
-rw-r--r--nvidia-installer.h4
-rw-r--r--precompiled.c37
-rw-r--r--precompiled.h8
-rw-r--r--sanity.c19
-rw-r--r--update.c167
17 files changed, 840 insertions, 393 deletions
diff --git a/DRIVER_VERSION b/DRIVER_VERSION
index 5d684b5..0d7760f 100644
--- a/DRIVER_VERSION
+++ b/DRIVER_VERSION
@@ -1 +1 @@
-1.0-9755
+100.14.03
diff --git a/backup.c b/backup.c
index dbb168c..c0efef3 100644
--- a/backup.c
+++ b/backup.c
@@ -120,13 +120,15 @@ typedef struct {
static BackupInfo *read_backup_log_file(Options *op);
+static void free_backup_info(BackupInfo *b);
+
static int check_backup_log_entries(Options *op, BackupInfo *b);
static int do_uninstall(Options *op);
static int sanity_check_backup_log_entries(Options *op, BackupInfo *b);
-
+static char *create_backwards_compatible_version_string(const char *str);
@@ -141,6 +143,7 @@ static int sanity_check_backup_log_entries(Options *op, BackupInfo *b);
int init_backup(Options *op, Package *p)
{
+ char *version;
FILE *log;
/* remove the directory, if it already exists */
@@ -168,9 +171,13 @@ int init_backup(Options *op, Package *p)
/* write the version and description */
- fprintf(log, "%s\n", p->version_string);
- fprintf(log, "%s\n", p->description);
+ version = create_backwards_compatible_version_string(p->version);
+ fprintf(log, "%s\n", version);
+ fprintf(log, "%s\n", p->description);
+
+ nvfree(version);
+
/* close the log file */
if (fclose(log) != 0) {
@@ -494,9 +501,9 @@ static int do_uninstall(Options *op)
"Your driver installation has been "
"altered since it was initially installed; this may happen, "
"for example, if you have since installed the NVIDIA driver through "
- "a mechanism other than the nvidia-installer (such as rpm or "
- "with the NVIDIA tarballs). The nvidia-installer will "
- "attempt to uninstall as best it can.";
+ "a mechanism other than nvidia-installer (such as your "
+ "distribution's native package management system). "
+ "nvidia-installer will attempt to uninstall as best it can.";
/* do we even have a backup directory? */
@@ -643,6 +650,8 @@ static int do_uninstall(Options *op)
/* XXX what to do if this fails?... nothing */
}
+ free_backup_info(b);
+
return TRUE;
} /* do_uninstall() */
@@ -743,6 +752,8 @@ static BackupInfo *read_backup_log_file(Options *op)
b->e = (BackupLogEntry *)
nvrealloc(b->e, sizeof(BackupLogEntry) * b->n);
+ memset(&b->e[b->n - 1], 0, sizeof(BackupLogEntry));
+
e = &b->e[b->n - 1];
e->num = num;
e->filename = filename;
@@ -825,6 +836,33 @@ static BackupInfo *read_backup_log_file(Options *op)
} /* read_backup_log_file() */
+
+/*
+ * free_backup_info() - free the data associated with BackupInfo
+ */
+
+static void free_backup_info(BackupInfo *b)
+{
+ int i;
+
+ if (!b) return;
+
+ nvfree(b->version);
+ nvfree(b->description);
+
+ for (i = 0; i < b->n; i++) {
+ nvfree(b->e[i].filename);
+ nvfree(b->e[i].target);
+ }
+
+ nvfree((char *) b->e);
+
+ nvfree((char *) b);
+
+} /* free_backup_info() */
+
+
+
/*
* check_backup_log_entries() - for each backup log entry, perform
* some basic sanity checks. Set the 'ok' field to FALSE if a
@@ -982,12 +1020,14 @@ static int check_backup_log_entries(Options *op, BackupInfo *b)
* XXX we should probably check the file permissions of BACKUP_LOG.
*/
-char *get_installed_driver_version_and_descr(Options *op, int *major,
- int *minor, int *patch)
+int get_installed_driver_version_and_descr(Options *op,
+ char **pVersion, char **pDescr)
{
struct stat stat_buf;
char *c, *version = NULL, *descr = NULL, *buf = NULL;
+ char *version_line = NULL;
int length, fd = -1;
+ int ret = FALSE;
if ((fd = open(BACKUP_LOG, O_RDONLY)) == -1) goto done;
@@ -1000,18 +1040,31 @@ char *get_installed_driver_version_and_descr(Options *op, int *major,
buf = mmap(0, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0);
if (!buf) goto done;
- version = get_next_line(buf, &c, buf, length);
- if (!version) goto done;
+ version_line = get_next_line(buf, &c, buf, length);
+ if (!version_line) goto done;
+
+ version = extract_version_string(version_line);
- if (!nvid_version(version, major, minor, patch)) goto done;
+ if (!version) goto done;
descr = get_next_line(c, NULL, buf, length);
+ if (!descr) goto done;
+
+ *pVersion = strdup(version);
+ *pDescr = strdup(descr);
+
+ ret = TRUE;
+
done:
- if (version) free(version);
+ nvfree(version_line);
+ nvfree(version);
+ nvfree(descr);
+
if (buf) munmap(buf, stat_buf.st_size);
if (fd != -1) close(fd);
- return descr;
+
+ return ret;
} /* get_installed_driver_version_and_descr() */
@@ -1033,38 +1086,44 @@ char *get_installed_driver_version_and_descr(Options *op, int *major,
int check_for_existing_driver(Options *op, Package *p)
{
- int major, minor, patch;
- char *descr;
+ char *descr = NULL;
+ char *version = NULL;
+ int ret = FALSE;
+ int localRet;
- if (!check_for_existing_rpms(op)) return FALSE;
+ if (!check_for_existing_rpms(op)) goto done;
- descr = get_installed_driver_version_and_descr(op, &major, &minor, &patch);
+ localRet = get_installed_driver_version_and_descr(op, &version, &descr);
if (op->kernel_module_only) {
- if (!descr) {
+ if (!localRet) {
ui_error(op, "No NVIDIA driver is currently installed; the "
"'--kernel-module-only' option can only be used "
"to install the NVIDIA kernel module on top of an "
"existing driver installation.");
- return FALSE;
+ goto done;
} else {
- if ((p->major != major) ||
- (p->minor != minor) ||
- (p->patch != patch)) {
+ if (strcmp(p->version, version) != 0) {
ui_error(op, "The '--kernel-module-only' option can only be "
"used to install a kernel module on top of an "
"existing driver installation of the same driver "
"version. The existing driver installation is "
- "%d.%d-%d, but the kernel module is %d.%d-%d\n",
- major, minor, patch, p->major, p->minor, p->patch);
- return FALSE;
+ "%s, but the kernel module is %s.\n",
+ version, p->version);
+ goto done;
} else {
- return TRUE;
+ ret = TRUE;
+ goto done;
}
}
}
- if (!descr) return TRUE;
+ /* no existing driver -- it is fine to continue with installation */
+
+ if (!localRet) {
+ ret = TRUE;
+ goto done;
+ }
/*
* XXX we could do a comparison, here, to check that the Package
@@ -1075,19 +1134,24 @@ int check_for_existing_driver(Options *op, Package *p)
*/
if (!ui_yes_no(op, TRUE, "There appears to already be a driver installed "
- "on your system (version: %d.%d-%d). As part of "
- "installing this driver (version: %d.%d-%d), the existing "
+ "on your system (version: %s). As part of "
+ "installing this driver (version: %s), the existing "
"driver will be uninstalled. Are you sure you want to "
"continue? ('no' will abort installation)",
- major, minor, patch, p->major, p->minor, p->patch)) {
+ version, p->version)) {
- free(descr);
ui_log(op, "Installation aborted.");
- return FALSE;
+ goto done;
}
- free(descr);
- return TRUE;
+ ret = TRUE;
+
+ done:
+
+ nvfree(descr);
+ nvfree(version);
+
+ return ret;
} /* check_for_existing_driver() */
@@ -1103,11 +1167,12 @@ int check_for_existing_driver(Options *op, Package *p)
int uninstall_existing_driver(Options *op, const int interactive)
{
- int major, minor, patch, ret;
- char *descr;
+ int ret;
+ char *descr = NULL;
+ char *version = NULL;
- descr = get_installed_driver_version_and_descr(op, &major, &minor, &patch);
- if (!descr) {
+ ret = get_installed_driver_version_and_descr(op, &version, &descr);
+ if (!ret) {
if (interactive) {
ui_message(op, "There is no NVIDIA driver currently installed.");
}
@@ -1118,17 +1183,18 @@ int uninstall_existing_driver(Options *op, const int interactive)
if (ret) {
if (interactive) {
- ui_message(op, "Uninstallation of existing driver: %s (%d.%d-%d) "
- "is complete.", descr, major, minor, patch);
+ ui_message(op, "Uninstallation of existing driver: %s (%s) "
+ "is complete.", descr, version);
} else {
- ui_log(op, "Uninstallation of existing driver: %s (%d.%d-%d) "
- "is complete.", descr, major, minor, patch);
+ ui_log(op, "Uninstallation of existing driver: %s (%s) "
+ "is complete.", descr, version);
}
} else {
ui_error(op, "Uninstallation failed.");
}
- free(descr);
+ nvfree(descr);
+ nvfree(version);
return TRUE;
@@ -1143,19 +1209,21 @@ int uninstall_existing_driver(Options *op, const int interactive)
int report_driver_information(Options *op)
{
- int major, minor, patch;
- char *descr;
-
- descr = get_installed_driver_version_and_descr(op, &major, &minor, &patch);
- if (!descr) {
+ char *descr, *version;
+ int ret;
+
+ ret = get_installed_driver_version_and_descr(op, &version, &descr);
+ if (!ret) {
ui_message(op, "There is no NVIDIA driver currently installed.");
return FALSE;
}
ui_message(op, "The currently installed driver is: '%s' "
- "(version: %d.%d-%d).", descr, major, minor, patch);
+ "(version: %s).", descr, version);
- free(descr);
+ nvfree(descr);
+ nvfree(version);
+
return TRUE;
} /* report_driver_information() */
@@ -1176,7 +1244,9 @@ int test_installed_files(Options *op)
ret = sanity_check_backup_log_entries(op, b);
- /* XXX should free resources associated with b */
+ /* free resources associated with b */
+
+ free_backup_info(b);
return ret;
@@ -1193,7 +1263,7 @@ int find_installed_file(Options *op, char *filename)
{
BackupInfo *b;
BackupLogEntry *e;
- int i;
+ int i, ret = FALSE;
if ((b = read_backup_log_file(op)) == NULL) return FALSE;
@@ -1204,13 +1274,14 @@ int find_installed_file(Options *op, char *filename)
/* XXX should maybe compare inodes rather than
filenames? */
- return TRUE;
+ ret = TRUE;
+ break;
}
}
- /* XXX need to free b */
+ free_backup_info(b);
- return FALSE;
+ return ret;
} /* find_installed_file() */
@@ -1330,3 +1401,61 @@ static int sanity_check_backup_log_entries(Options *op, BackupInfo *b)
return ret;
} /* sanity_check_backup_log_entries */
+
+
+
+/*
+ * create_backwards_compatible_version_string() - given the version
+ * string 'str', generate a version string to write to the backup log
+ * file that can be read by older nvidia-installers that assumed the
+ * X.Y-ZZZZ version format.
+ *
+ * Fortunately, old nvidia-installers' version parsing didn't care if
+ * there were extra digits beyond the four Z's (e.g., it could be
+ * X.Y-ZZZZZ, or X.Y-ZZZZZZZZ); they would just look for the first 4
+ * Z's if they needed to parse the version.
+ *
+ * So, the strategy is to take the new version string, remove any
+ * periods, and print that out as the old style version, followed by
+ * the real version string in parenthesis; e.g.,
+ *
+ * "1.0-105917 (105.9.17)"
+ *
+ * In this way, an old nvidia-installer will atleast be able to parse
+ * the string, even though it may not understand it, but a new
+ * nvidia-installer can be smart and pull out the new version string.
+ */
+
+static char *create_backwards_compatible_version_string(const char *str)
+{
+ char *version, *scratch, *s, *t;
+ int len;
+
+ /*
+ * create a scratch string by duping the passed in str, but
+ * collapse the scratch string by only retaining the digits; e.g.,
+ * "105.9.17" --> "105917"
+ */
+
+ scratch = nvstrdup(str);
+
+ for (s = t = scratch; *t; t++) {
+ if (isdigit(*t)) {
+ *s++ = *t;
+ }
+ }
+
+ *s = '\0';
+
+ /* allocate a new string to contain the result */
+
+ len = strlen(str);
+ version = nvalloc((len * 2) + 16);
+
+ sprintf(version, "1.0-%s (%s)", scratch, str);
+
+ nvfree(scratch);
+
+ return version;
+
+} /* create_backwards_compatible_version_string() */
diff --git a/backup.h b/backup.h
index c571296..464fe6a 100644
--- a/backup.h
+++ b/backup.h
@@ -36,12 +36,11 @@ int init_backup (Options*, Package*);
int do_backup (Options*, const char*);
int log_install_file (Options*, const char*);
int log_create_symlink (Options*, const char*, const char*);
-int get_installed_driver_version(Options*, int*, int*, int*);
int check_for_existing_driver (Options*, Package*);
int uninstall_existing_driver (Options*, const int);
int report_driver_information (Options*);
-char *get_installed_driver_version_and_descr(Options *, int *, int *, int *);
+int get_installed_driver_version_and_descr(Options *, char **, char **);
int test_installed_files(Options *op);
int find_installed_file(Options *op, char *filename);
diff --git a/command-list.c b/command-list.c
index c768d8c..963097b 100644
--- a/command-list.c
+++ b/command-list.c
@@ -47,6 +47,8 @@
#include "kernel.h"
+static void free_file_list(FileList* l);
+
static void find_conflicting_xfree86_libraries(Options *,
const char *,
FileList *);
@@ -190,6 +192,8 @@ CommandList *build_command_list(Options *op, Package *p)
if (find_installed_file(op, l->filename[i])) {
ui_error(op, "The file '%s' already exists as part of this "
"driver installation.", l->filename[i]);
+ free_file_list(l);
+ free_command_list(op, c);
return NULL;
}
}
@@ -318,10 +322,7 @@ CommandList *build_command_list(Options *op, Package *p)
}
/* free the FileList */
-
- for (i = 0; i < l->num; i++) free(l->filename[i]);
- free(l->filename);
- free(l);
+ free_file_list(l);
return c;
@@ -330,6 +331,27 @@ CommandList *build_command_list(Options *op, Package *p)
/*
+ * free_file_list() - free the file list
+ */
+
+static void free_file_list(FileList* l)
+{
+ int i;
+
+ if (!l) return;
+
+ for (i = 0; i < l->num; i++) {
+ nvfree(l->filename[i]);
+ }
+
+ nvfree((char *) l->filename);
+ nvfree((char *) l);
+
+} /* free_file_list() */
+
+
+
+/*
* free_command_list() - free the specified commandlist
*/
@@ -402,7 +424,10 @@ int execute_command_list(Options *op, CommandList *c,
c->cmds[i].s0, data);
ret = continue_after_error(op, "Failed to execute `%s`",
c->cmds[i].s0);
- if (!ret) return FALSE;
+ if (!ret) {
+ nvfree(data);
+ return FALSE;
+ }
}
if (data) free(data);
break;
diff --git a/files.c b/files.c
index fb028d5..9c1afef 100644
--- a/files.c
+++ b/files.c
@@ -1409,7 +1409,6 @@ int copy_directory_contents(Options *op, const char *src, const char *dst)
int pack_precompiled_kernel_interface(Options *op, Package *p)
{
char *cmd, time_str[256], *proc_version_string;
- char major[16], minor[16], patch[16];
char *result, *descr;
time_t t;
struct utsname buf;
@@ -1430,12 +1429,6 @@ int pack_precompiled_kernel_interface(Options *op, Package *p)
proc_version_string = read_proc_version(op);
- /* get the version strings */
-
- snprintf(major, 16, "%d", p->major);
- snprintf(minor, 16, "%d", p->minor);
- snprintf(patch, 16, "%d", p->patch);
-
/* use the uname string as the description */
uname(&buf);
@@ -1451,12 +1444,10 @@ int pack_precompiled_kernel_interface(Options *op, Package *p)
PRECOMPILED_KERNEL_INTERFACE_FILENAME,
" --output=", p->precompiled_kernel_interface_directory,
"/", PRECOMPILED_KERNEL_INTERFACE_FILENAME,
- "-", p->version_string, ".", time_str,
+ "-", p->version, ".", time_str,
" --description=\"", descr, "\"",
" --proc-version=\"", proc_version_string, "\"",
- " --major=", major,
- " --minor=", minor,
- " --patch=", patch, NULL);
+ " --version=", p->version, NULL);
/* execute the command */
@@ -1977,6 +1968,66 @@ static char *get_xdg_data_dir(void)
}
+
+/*
+ * extract_x_path() - take a comma-separated list of directories, and
+ * extract the next available directory in the list. Assign the
+ * 'next' pointer so that it points to where we should continue during
+ * the next call of extract_x_path().
+ *
+ * On success, return a pointer to the next directory in the string,
+ * and update the 'next' pointer. When we have exhausted the list,
+ * NULL is returned.
+ *
+ * Note that this will destructively replace commas with NULL
+ * terminators in the string.
+ */
+
+static char *extract_x_path(char *str, char **next)
+{
+ char *start;
+
+ /*
+ * choose where to start in the string: either we start at the
+ * beginning, or we start immediately after where we found a comma
+ * last time
+ */
+
+ start = str;
+
+ if (*next) start = *next;
+
+ /* skip past any commas at the start */
+
+ while (*start == ',') start++;
+
+ /* if we hit the end of the string, return now */
+
+ if (*start == '\0') return NULL;
+
+ /*
+ * find the next comma in the string; if we find one, change it to
+ * a NULL terminator (and move 'next' to the character immediately
+ * after the comma); if we don't find a comma, move the 'next'
+ * pointer to the end of the string, so that we terminate on the
+ * next call to extract_x_path()
+ */
+
+ *next = strchr(start, ',');
+
+ if (*next) {
+ **next = '\0';
+ (*next)++;
+ } else {
+ *next = strchr(start, '\0');
+ }
+
+ return start;
+
+} /* extract_x_path() */
+
+
+
/*
* get_x_paths_helper() - helper function for determining the X
* library and module paths; returns 'TRUE' if we had to guess at the
@@ -1990,7 +2041,7 @@ static int get_x_paths_helper(Options *op,
char *name,
char **path)
{
- char *dir, *cmd;
+ char *dirs, *cmd, *dir, *next;
int ret, guessed = 0;
/*
@@ -2003,94 +2054,121 @@ static int get_x_paths_helper(Options *op,
}
/*
- * if this is a modular X server, then attempt to determine the
- * path through the various query mechanisms
+ * attempt to determine the path through the various query mechanisms
+ *
+ * xorg-server >= 1.3 has a stupid version number regression because the
+ * reported Xorg version was tied to the server version, meaning what used
+ * to report 7.2 now reports, for example, 1.2.99.903. This means we set
+ * op->modular_xorg to FALSE. However, any server with this regression will
+ * also support the -showDefaultModulePath option so we should still be able
+ * to get the right path.
*/
-
- if (op->modular_xorg) {
-
- /*
- * first, try the X server commandline option; this is the
- * recommended query mechanism as of X.Org 7.2
- */
-
- if (op->utils[XSERVER]) {
-
- dir = NULL;
- cmd = nvstrcat(op->utils[XSERVER], " ", xserver_cmd, NULL);
- ret = run_command(op, cmd, &dir, FALSE, 0, TRUE);
- nvfree(cmd);
+
+ /*
+ * first, try the X server commandline option; this is the
+ * recommended query mechanism as of X.Org 7.2
+ */
+ if (op->utils[XSERVER]) {
+
+ dirs = NULL;
+ cmd = nvstrcat(op->utils[XSERVER], " ", xserver_cmd, NULL);
+ ret = run_command(op, cmd, &dirs, FALSE, 0, TRUE);
+ nvfree(cmd);
+
+ if ((ret == 0) && dirs) {
+
+ next = NULL;
+
+ dir = extract_x_path(dirs, &next);
- if ((ret == 0) && dir) {
+ while (dir) {
if (directory_exists(op, dir)) {
ui_expert(op, "X %s path '%s' determined from `%s %s`",
name, dir, op->utils[XSERVER], xserver_cmd);
- *path = dir;
+ *path = nvstrdup(dir);
+
+ nvfree(dirs);
+
return FALSE;
-
+
} else {
ui_warn(op, "You appear to be using a modular X.Org "
"release, but the X %s installation "
- "path reported by `%s %s` does not exist. "
+ "path, '%s', reported by `%s %s` does not exist. "
"Please check your X.Org installation.",
- name, op->utils[XSERVER], xserver_cmd);
+ name, dir, op->utils[XSERVER], xserver_cmd);
}
+
+ dir = extract_x_path(dirs, &next);
}
-
- nvfree(dir);
}
-
- /*
- * then, try the pkg-config command; this was the the
- * pseudo-recommended query mechanism between X.Org 7.0 and
- * X.Org 7.2
- */
-
- if (op->utils[PKG_CONFIG]) {
-
- dir = NULL;
- cmd = nvstrcat(op->utils[PKG_CONFIG], " ",
- pkg_config_cmd, NULL);
- ret = run_command(op, cmd, &dir, FALSE, 0, TRUE);
- nvfree(cmd);
+
+ nvfree(dirs);
+ }
+
+ /*
+ * then, try the pkg-config command; this was the the
+ * pseudo-recommended query mechanism between X.Org 7.0 and
+ * X.Org 7.2
+ */
+ if (op->utils[PKG_CONFIG]) {
+
+ dirs = NULL;
+ cmd = nvstrcat(op->utils[PKG_CONFIG], " ",
+ pkg_config_cmd, NULL);
+ ret = run_command(op, cmd, &dirs, FALSE, 0, TRUE);
+ nvfree(cmd);
+
+ if ((ret == 0) && dirs) {
+
+ next = NULL;
- if ((ret == 0) && dir) {
+ dir = extract_x_path(dirs, &next);
+
+ while (dir) {
if (directory_exists(op, dir)) {
-
+
ui_expert(op, "X %s path '%s' determined from `%s %s`",
name, dir, op->utils[PKG_CONFIG],
pkg_config_cmd);
+
+ *path = nvstrdup(dir);
+
+ nvfree(dirs);
- *path = dir;
return FALSE;
-
+
} else {
ui_warn(op, "You appear to be using a modular X.Org "
"release, but the X %s installation "
- "path reported by `%s %s` does not exist. "
+ "path, '%s', reported by `%s %s` does not exist. "
"Please check your X.Org installation.",
- name, op->utils[PKG_CONFIG], pkg_config_cmd);
+ name, dir, op->utils[PKG_CONFIG], pkg_config_cmd);
}
+
+ dir = extract_x_path(dirs, &next);
}
-
- nvfree(dir);
}
-
- /*
- * neither of the above mechanisms yielded a usable path; fall
- * through to constructing the path by hand; record that we
- * have to guess the path so that we can print a warning when
- * we are done
- */
-
- guessed = TRUE;
+
+ nvfree(dirs);
}
-
-
+
+ /*
+ * neither of the above mechanisms yielded a usable path; fall
+ * through to constructing the path by hand. If this is a modular X server,
+ * record that we have to guess the path so that we can print a warning when
+ * we are done. For non-modular X, the default of /usr/X11R6/lib is
+ * standard.
+ */
+
+ if (op->modular_xorg)
+ guessed = TRUE;
+
+
/* build the path */
if (library) {
diff --git a/install-from-cwd.c b/install-from-cwd.c
index 90f7285..17b8ac2 100644
--- a/install-from-cwd.c
+++ b/install-from-cwd.c
@@ -55,6 +55,7 @@
static Package *parse_manifest(Options *op);
static int install_kernel_module(Options *op, Package *p);
+static void free_package(Package *p);
/*
@@ -96,9 +97,8 @@ int install_from_cwd(Options *op)
if ((p = parse_manifest(op)) == NULL) goto failed;
- ui_set_title(op, "%s (%d.%d-%d)", p->description,
- p->major, p->minor, p->patch);
-
+ ui_set_title(op, "%s (%s)", p->description, p->version);
+
/*
* warn the user if "legacy" GPUs are installed in this system
* and if no supported GPU is found, at all.
@@ -116,14 +116,14 @@ int install_from_cwd(Options *op)
/* ask the user to accept the license */
- if (!get_license_acceptance(op)) return FALSE;
+ if (!get_license_acceptance(op)) goto exit_install;
/*
* determine the current NVIDIA version (if any); ask the user if
* they really want to overwrite the existing installation
*/
- if (!check_for_existing_driver(op, p)) return FALSE;
+ if (!check_for_existing_driver(op, p)) goto exit_install;
/* attempt to build a kernel module for the target kernel */
@@ -211,7 +211,9 @@ int install_from_cwd(Options *op)
/* call the ui to get approval for the list of commands */
- if (!ui_approve_command_list(op, c, "%s", p->description)) return FALSE;
+ if (!ui_approve_command_list(op, c, "%s", p->description)) {
+ goto exit_install;
+ }
/* initialize the backup log file */
@@ -238,7 +240,7 @@ int install_from_cwd(Options *op)
if (op->kernel_module_only) {
ui_message(op, "Installation of the kernel module for the %s "
"(version %s) is now complete.",
- p->description, p->version_string);
+ p->description, p->version);
} else {
/* ask the user if they would like to run nvidia-xconfig */
@@ -257,7 +259,7 @@ int install_from_cwd(Options *op)
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_string);
+ "complete.", p->description, p->version);
} else {
if ((op->distro == SUSE) || (op->distro == UNITED_LINUX)) {
@@ -268,14 +270,21 @@ int install_from_cwd(Options *op)
ui_message(op, "Installation of the %s (version: %s) is now "
"complete. %s", p->description,
- p->version_string, msg);
+ p->version, msg);
}
}
+ free_package(p);
+
return TRUE;
failed:
+ /*
+ * something bad happened during installation; print an error
+ * message and return FALSE
+ */
+
if (op->logging) {
ui_error(op, "Installation has failed. Please see the file '%s' "
"for details. You may find suggestions on fixing "
@@ -288,6 +297,18 @@ int install_from_cwd(Options *op)
"on the Linux driver download page at www.nvidia.com.");
}
+ /* fall through into exit_install... */
+
+ exit_install:
+
+ /*
+ * we are exiting installation; this can happen for reasons that
+ * do not merit the error message (e.g., the user declined the
+ * license agreement)
+ */
+
+ free_package(p);
+
return FALSE;
} /* install_from_cwd() */
@@ -411,6 +432,8 @@ int add_this_kernel(Options *op)
if (!pack_precompiled_kernel_interface(op, p)) goto failed;
+ free_package(p);
+
return TRUE;
failed:
@@ -418,6 +441,8 @@ int add_this_kernel(Options *op)
ui_error(op, "Unable to add a precompiled kernel interface for the "
"running kernel.");
+ free_package(p);
+
return FALSE;
} /* add_this_kernel() */
@@ -431,7 +456,7 @@ int add_this_kernel(Options *op)
* The first nine lines of the .manifest file are:
*
* - a description string
- * - a version string of the form "major.minor-patch"
+ * - a version string
* - the kernel module file name
* - the kernel interface file name
* - the kernel module name (what `rmmod` and `modprobe` should use)
@@ -458,7 +483,7 @@ static Package *parse_manifest (Options *op)
{
char *buf, *c, *flag , *tmpstr;
int done, n, line;
- int fd, len = 0;
+ int fd, ret, len = 0;
struct stat stat_buf;
Package *p;
char *manifest = MAP_FAILED, *ptr;
@@ -490,10 +515,8 @@ static Package *parse_manifest (Options *op)
/* the second line is the version */
line++;
- p->version_string = get_next_line(ptr, &ptr, manifest, len);
- if (!p->version_string) goto invalid_manifest_file;
- if (!nvid_version(p->version_string, &p->major, &p->minor, &p->patch))
- goto invalid_manifest_file;
+ p->version = get_next_line(ptr, &ptr, manifest, len);
+ if (!p->version) goto invalid_manifest_file;
/* new third line is the kernel interface filename */
@@ -574,7 +597,10 @@ static Package *parse_manifest (Options *op)
do {
buf = get_next_line(ptr, &ptr, manifest, len);
- if ((!buf) || (buf[0] == '\0')) {
+ if (!buf) {
+ done = TRUE;
+ } else if (buf[0] == '\0') {
+ free(buf);
done = TRUE;
} else {
@@ -590,23 +616,29 @@ static Package *parse_manifest (Options *op)
goto fail;
}
+ /* initialize the new entry */
+
+ memset(&p->entries[n], 0, sizeof(PackageEntry));
+
/* read the file name and permissions */
c = buf;
p->entries[n].file = read_next_word(buf, &c);
+
+ if (!p->entries[n].file) goto invalid_manifest_file;
+
tmpstr = read_next_word(c, &c);
- /* if any of them were NULL, fail */
-
- if (!p->entries[n].file || !tmpstr) goto invalid_manifest_file;
+ if (!tmpstr) goto invalid_manifest_file;
/* translate the mode string into an octal mode */
- if (!mode_string_to_mode(op, tmpstr, &p->entries[n].mode)) {
- goto invalid_manifest_file;
- }
+ ret = mode_string_to_mode(op, tmpstr, &p->entries[n].mode);
+
free(tmpstr);
+
+ if (!ret) goto invalid_manifest_file;
/* every file has a type field */
@@ -754,10 +786,63 @@ static Package *parse_manifest (Options *op)
goto fail;
fail:
- if (p && p->entries) free(p->entries);
- if (p) free(p);
+ free_package(p);
if (manifest != MAP_FAILED) munmap(manifest, len);
if (fd != -1) close(fd);
return NULL;
} /* parse_manifest() */
+
+
+
+/*
+ * free_package() - free the Package data structure
+ */
+
+static void free_package(Package *p)
+{
+ int i;
+
+ if (!p) return;
+
+ nvfree(p->description);
+ nvfree(p->version);
+ nvfree(p->kernel_module_filename);
+ nvfree(p->kernel_interface_filename);
+ nvfree(p->kernel_module_name);
+
+ if (p->bad_modules) {
+ for (i = 0; p->bad_modules[i]; i++) {
+ nvfree(p->bad_modules[i]);
+ }
+ nvfree((char *) p->bad_modules);
+ }
+
+ if (p->bad_module_filenames) {
+ for (i = 0; p->bad_module_filenames[i]; i++) {
+ nvfree(p->bad_module_filenames[i]);
+ }
+ nvfree((char *) p->bad_module_filenames);
+ }
+
+ nvfree(p->kernel_module_build_directory);
+
+ nvfree(p->precompiled_kernel_interface_directory);
+
+ for (i = 0; i < p->num_entries; i++) {
+ nvfree(p->entries[i].file);
+ nvfree(p->entries[i].path);
+ nvfree(p->entries[i].target);
+ nvfree(p->entries[i].dst);
+
+ /*
+ * Note: p->entries[i].name just points into
+ * p->entries[i].file, so don't free p->entries[i].name
+ */
+ }
+
+ nvfree((char *) p->entries);
+
+ nvfree((char *) p);
+
+} /* free_package() */
diff --git a/kernel.c b/kernel.c
index e3692c4..f0d8c5c 100644
--- a/kernel.c
+++ b/kernel.c
@@ -828,50 +828,6 @@ int load_kernel_module(Options *op, Package *p)
-
-
-
-/*
- * check_kernel_module_version() - check that the driver version
- * indicated in the /proc filesystem is the same as the driver version
- * specified in the package description.
- */
-
-int check_kernel_module_version(Options *op, Package *p)
-{
- int major, minor, patch;
- int proc_major, proc_minor, proc_patch;
- FILE *fp = 0;
- char *buf;
- int eof;
-
- fp = fopen(NVIDIA_VERSION_PROC_FILE, "r");
- if (!fp)
- return FALSE;
- buf = fget_next_line(fp, &eof);
- fclose(fp);
-
- if (!nvid_version(buf, &proc_major, &proc_minor, &proc_patch)) {
- free(buf);
- return FALSE;
- }
-
- if (!nvid_version(p->version_string, &major, &minor, &patch)) {
- return FALSE;
- }
-
- if ((proc_major != major) ||
- (proc_minor != minor) ||
- (proc_patch != patch)) {
- return FALSE;
- }
-
- return TRUE;
-
-} /* check_kernel_module_version() */
-
-
-
/*
* check_for_unloaded_kernel_module() - test if any of the "bad"
* kernel modules are loaded; if they are, then try to unload it. If
@@ -1343,7 +1299,7 @@ download_updated_kernel_interface(Options *op, Package *p,
tmpfile = nvstrcat(op->tmpdir, "/nv-updates-XXXXXX", NULL);
url = nvstrcat(op->ftp_site, "/XFree86/", INSTALLER_OS, "-",
- INSTALLER_ARCH, "/", p->version_string,
+ INSTALLER_ARCH, "/", p->version,
"/updates/updates.txt", NULL);
/*
@@ -1407,7 +1363,7 @@ download_updated_kernel_interface(Options *op, Package *p,
nvfree(url);
url = nvstrcat(op->ftp_site, "/XFree86/",
INSTALLER_OS, "-", INSTALLER_ARCH, "/",
- p->version_string, "/updates/", buf, NULL);
+ p->version, "/updates/", buf, NULL);
dstfile = nvstrcat(p->precompiled_kernel_interface_directory,
"/", buf, NULL);
@@ -1440,7 +1396,7 @@ download_updated_kernel_interface(Options *op, Package *p,
info = precompiled_unpack(op, dstfile, output_filename,
proc_version_string,
- p->major, p->minor, p->patch);
+ p->version);
/* compare checksums */
@@ -1665,7 +1621,7 @@ static PrecompiledInfo *scan_dir(Options *op, Package *p,
info = precompiled_unpack(op, filename, output_filename,
proc_version_string,
- p->major, p->minor, p->patch);
+ p->version);
if (info) break;
@@ -1788,15 +1744,15 @@ static char *guess_kernel_module_filename(Options *op)
minor = atoi(dot0);
if ((major > 2) || ((major == 2) && (minor > 4))) {
- return "nvidia.ko";
+ return nvstrdup("nvidia.ko");
} else {
- return "nvidia.o";
+ return nvstrdup("nvidia.o");
}
fail:
ui_error (op, "Unable to determine if kernel is 2.6.0 or greater from "
"uname string '%s'; assuming the kernel module filename is "
"'nvidia.o'.", str);
- return "nvidia.o";
+ return nvstrdup("nvidia.o");
} /* guess_kernel_module_filename() */
diff --git a/kernel.h b/kernel.h
index 3e9bb27..ca72742 100644
--- a/kernel.h
+++ b/kernel.h
@@ -36,7 +36,6 @@ int build_kernel_module (Options*, Package*);
int build_kernel_interface (Options*, Package*);
int test_kernel_module (Options*, Package*);
int load_kernel_module (Options*, Package*);
-int check_kernel_module_version (Options*, Package*);
int check_for_unloaded_kernel_module (Options*, Package*);
int find_precompiled_kernel_interface (Options*, Package*);
char *get_kernel_name (Options*);
diff --git a/misc.c b/misc.c
index 52d91ca..d0bbb6d 100644
--- a/misc.c
+++ b/misc.c
@@ -1008,51 +1008,6 @@ char *find_system_util(const char *util)
/*
- * nvid_version() - parse the given nvid string for the version
- * number, and assign major, minor and patch. Returns TRUE on
- * success, FALSE on failure.
- *
- * The version format is assumed to be: is X.Y-ZZZZ
- */
-
-int nvid_version (const char *str, int *major, int *minor, int *patch)
-{
- char *s, *x;
- int ret = FALSE;
-
- s = nvstrdup(str);
- x = s;
-
- while (*x) {
- if (((x[0]) && isdigit(x[0])) &&
- ((x[1]) && (x[1] == '.')) &&
- ((x[2]) && isdigit(x[2])) &&
- ((x[3]) && (x[3] == '-')) &&
- ((x[4]) && isdigit(x[4])) &&
- ((x[5]) && isdigit(x[5])) &&
- ((x[6]) && isdigit(x[6])) &&
- ((x[7]) && isdigit(x[7]))) {
-
- x[1] = x[3] = x[8] = '\0';
-
- *major = atoi(&x[0]);
- *minor = atoi(&x[2]);
- *patch = atoi(&x[4]);
-
- ret = TRUE;
- break;
- }
- x++;
- }
-
- free(s);
- return ret;
-
-} /* nvid_version() */
-
-
-
-/*
* continue_after_error() - tell the user that an error has occured,
* and ask them if they would like to continue.
*
@@ -1087,10 +1042,10 @@ int do_install(Options *op, Package *p, CommandList *c)
char *msg;
int len, ret;
- len = strlen(p->description) + strlen(p->version_string) + 64;
+ len = strlen(p->description) + strlen(p->version) + 64;
msg = (char *) nvalloc(len);
snprintf(msg, len, "Installing '%s' (%s):",
- p->description, p->version_string);
+ p->description, p->version);
ret = execute_command_list(op, c, msg, "Installing");
@@ -1107,6 +1062,175 @@ int do_install(Options *op, Package *p, CommandList *c)
/*
+ * extract_version_string() - extract the NVIDIA driver version string
+ * from the given string. On failure, return NULL; on success, return
+ * a malloced string containing just the version string.
+ *
+ * The version string can have one of two forms: either the old
+ * "X.Y.ZZZZ" format (e.g., "1.0-9742"), or the new format where it is
+ * just a collection of period-separated numbers (e.g., "105.17.2").
+ * The length and number of periods in the newer format is arbitrary.
+ *
+ * Furthermore, we expect the new version format to be enclosed either
+ * in parenthesis or whitespace (or be at the start or end of the
+ * input string) and be atleast 5 characters long. This allows us to
+ * distinguish the version string from other numbers such as the year
+ * or the old version format in input strings like this:
+ *
+ * "NVIDIA UNIX x86 Kernel Module 105.17.2 Fri Dec 15 09:54:45 PST 2006"
+ * "1.0-105917 (105.9.17)"
+ */
+
+char *extract_version_string(const char *str)
+{
+ char c, *copiedString, *start, *end, *x, *version = NULL;
+ int state;
+
+ if (!str) return NULL;
+
+ copiedString = strdup(str);
+ x = copiedString;
+
+ /*
+ * look for a block of only numbers and periods; the version
+ * string must be surrounded by either whitespace, or the
+ * start/end of the string; we use a small state machine to parse
+ * the string
+ */
+
+ start = NULL;
+ end = NULL;
+
+#define STATE_IN_VERSION 0
+#define STATE_NOT_IN_VERSION 1
+#define STATE_LOOKING_FOR_VERSION 2
+#define STATE_FOUND_VERSION 3
+
+ state = STATE_LOOKING_FOR_VERSION;
+
+ while (*x) {
+
+ c = *x;
+
+ switch (state) {
+
+ /*
+ * if we are LOOKING_FOR_VERSION, then finding a digit
+ * will put us inside the version, whitespace (or open
+ * parenthesis) will allow us to continue to look for the
+ * version, and any other character will cause us to stop
+ * looking for the version string
+ */
+
+ case STATE_LOOKING_FOR_VERSION:
+ if (isdigit(c)) {
+ start = x;
+ state = STATE_IN_VERSION;
+ } else if (isspace(c) || (c == '(')) {
+ state = STATE_LOOKING_FOR_VERSION;
+ } else {
+ state = STATE_NOT_IN_VERSION;
+ }
+ break;
+
+ /*
+ * if we are IN_VERSION, then a digit or period will keep
+ * us in the version, space (or close parenthesis) and
+ * more than 4 characters of version means we found the
+ * entire version string. If we find any other character,
+ * then what we thought was the version string wasn't, so
+ * move to NOT_IN_VERSION.
+ */
+
+ case STATE_IN_VERSION:
+ if (isdigit(c) || (c == '.')) {
+ state = STATE_IN_VERSION;
+ } else if ((isspace(c) || (c == ')')) && ((x - start) >= 5)) {
+ end = x;
+ state = STATE_FOUND_VERSION;
+ goto exit_while_loop;
+ } else {
+ state = STATE_NOT_IN_VERSION;
+ }
+ break;
+
+ /*
+ * if we are NOT_IN_VERSION, then space or open
+ * parenthesis will make us start looking for the version,
+ * and any other character just leaves us in the
+ * NOT_IN_VERSION state
+ */
+
+ case STATE_NOT_IN_VERSION:
+ if (isspace(c) || (c == '(')) {
+ state = STATE_LOOKING_FOR_VERSION;
+ } else {
+ state = STATE_NOT_IN_VERSION;
+ }
+ break;
+ }
+
+ x++;
+ }
+
+ /*
+ * the NULL terminator that broke us out of the while loop could
+ * be the end of the version string
+ */
+
+ if ((state == STATE_IN_VERSION) && ((x - start) >= 5)) {
+ end = x;
+ state = STATE_FOUND_VERSION;
+ }
+
+ exit_while_loop:
+
+ /* if we found a version string above, copy it */
+
+ if (state == STATE_FOUND_VERSION) {
+ *end = '\0';
+ version = strdup(start);
+ goto done;
+ }
+
+
+
+ /*
+ * we did not find a version string with the new format; look for
+ * a version of the old X.Y-ZZZZ format
+ */
+
+ x = copiedString;
+
+ while (*x) {
+ if (((x[0]) && isdigit(x[0])) &&
+ ((x[1]) && (x[1] == '.')) &&
+ ((x[2]) && isdigit(x[2])) &&
+ ((x[3]) && (x[3] == '-')) &&
+ ((x[4]) && isdigit(x[4])) &&
+ ((x[5]) && isdigit(x[5])) &&
+ ((x[6]) && isdigit(x[6])) &&
+ ((x[7]) && isdigit(x[7]))) {
+
+ x[8] = '\0';
+
+ version = strdup(x);
+ goto done;
+ }
+ x++;
+ }
+
+ done:
+
+ free(copiedString);
+
+ return version;
+
+} /* extract_version_string() */
+
+
+
+/*
* should_install_opengl_headers() - if in expert mode, ask the user
* if they want to install OpenGL header files.
*/
@@ -2097,7 +2221,7 @@ int check_for_nvidia_graphics_devices(Options *op, Package *p)
"ignore this GPU.",
LegacyList[i].AdapterString,
branch_string,
- p->version_string);
+ p->version);
found_legacy_device = TRUE;
}
}
@@ -2113,7 +2237,7 @@ int check_for_nvidia_graphics_devices(Options *op, Package *p)
"%s NVIDIA Linux graphics driver installed in this system. "
"For further details, please see the appendix SUPPORTED "
"NVIDIA GRAPHICS CHIPS in the README available on the Linux "
- "driver download page at www.nvidia.com.", p->version_string);
+ "driver download page at www.nvidia.com.", p->version);
return FALSE;
}
diff --git a/misc.h b/misc.h
index e563277..3c78b6d 100644
--- a/misc.h
+++ b/misc.h
@@ -103,7 +103,7 @@ int find_module_utils(Options *op);
int check_selinux(Options *op);
int check_proc_modprobe_path(Options *op);
int check_development_tools(Options *op, Package *p);
-int nvid_version (const char *str, int *major, int *minor, int *patch);
+char *extract_version_string(const char *str);
int continue_after_error(Options *op, const char *fmt, ...);
int do_install(Options *op, Package *p, CommandList *c);
void should_install_opengl_headers(Options *op, Package *p);
diff --git a/mkprecompiled.c b/mkprecompiled.c
index d8d11d3..e1f23d5 100644
--- a/mkprecompiled.c
+++ b/mkprecompiled.c
@@ -14,13 +14,7 @@
*
* -i, --interface=<filename>
* -o, --output=<filename>
- *
- * --major-version=<major>
- * --minor-version=<minor>
- * --patch-version=<patch>
- *
* -u, --unpack=<filename>
- *
* -d, --description=<kernel description>
*
* There is nothing specific to the NVIDIA graphics driver in this
@@ -32,12 +26,10 @@
* the first 8 bytes are: "NVIDIA "
*
* the next 4 bytes (unsigned) are: CRC of the kernel interface module
+ *
+ * the next 4 bytes (unsigned) are: the length of the version string (v)
*
- * the next 4 bytes (unsigned) are: major version
- *
- * the next 4 bytes (unsigned) are: minor version
- *
- * the next 4 bytes (unsigned) are: patch version
+ * the next v bytes are the version string
*
* the next 4 bytes (unsigned) are: the length of the description (n)
*
@@ -70,7 +62,7 @@
#define _GNU_SOURCE /* XXX not portable */
#include <getopt.h>
-#define CONSTANT_LENGTH (8 + 4 + 12 + 4 + 4)
+#define CONSTANT_LENGTH (8 + 4 + 4 + 4 + 4)
typedef unsigned int uint32;
typedef unsigned char uint8;
@@ -85,9 +77,7 @@ typedef struct {
char *unpack;
char *description;
char *proc_version_string;
- uint32 major;
- uint32 minor;
- uint32 patch;
+ char *version;
uint8 info;
uint8 match;
} Options;
@@ -241,10 +231,8 @@ void print_help(void)
printf("-v, --proc-version=<string>\n");
printf(" /proc/version string for target kernel.\n\n");
- printf("--major=<major version number>\n");
- printf("--minor=<minor version number>\n");
- printf("--patch=<patch version number>\n\n");
-
+ printf("--version=<version string>\n\n");
+
printf("--info\n");
printf(" Print the description and version number of the file\n");
printf(" specified by the unpack option.\n\n");
@@ -271,9 +259,6 @@ Options *parse_commandline(int argc, char *argv[])
Options *op;
int c, option_index = 0;
-#define MAJOR_VERSION_OPTION 1
-#define MINOR_VERSION_OPTION 2
-#define PATCH_VERSION_OPTION 3
#define INFO_OPTION 4
static struct option long_options[] = {
@@ -283,9 +268,7 @@ Options *parse_commandline(int argc, char *argv[])
{ "description", 1, 0, 'd' },
{ "help", 0, 0, 'h' },
{ "proc-version", 1, 0, 'v' },
- { "major", 1, 0, MAJOR_VERSION_OPTION },
- { "minor", 1, 0, MINOR_VERSION_OPTION },
- { "patch", 1, 0, PATCH_VERSION_OPTION },
+ { "version", 1, 0, 'V' },
{ "info", 0, 0, INFO_OPTION },
{ "match", 0, 0, 'm' },
{ 0, 0, 0, 0 }
@@ -306,12 +289,7 @@ Options *parse_commandline(int argc, char *argv[])
case 'd': op->description = optarg; break;
case 'h': print_help(); exit(0); break;
case 'v': op->proc_version_string = optarg; break;
- case MAJOR_VERSION_OPTION:
- op->major = atoi(optarg); break;
- case MINOR_VERSION_OPTION:
- op->minor = atoi(optarg); break;
- case PATCH_VERSION_OPTION:
- op->patch = atoi(optarg); break;
+ case 'V': op->version = optarg; break;
case INFO_OPTION:
op->info = 1; break;
case 'm':
@@ -347,6 +325,11 @@ Options *parse_commandline(int argc, char *argv[])
exit(1);
}
+ if (!op->version) {
+ fprintf(stderr, "Driver version string not specified.\n");
+ exit(1);
+ }
+
return op;
} /* parse_commandline() */
@@ -482,19 +465,21 @@ int pack(Options *op)
int fd, offset, src_fd;
uint8 *out, *src, data[4];
uint32 crc;
- int description_len, proc_version_len, interface_len, total_len;
+ int version_len, description_len, proc_version_len;
+ int interface_len, total_len;
/*
* get the lengths of the description, the proc version string,
* and the interface file.
*/
+ version_len = strlen(op->version);
description_len = strlen(op->description);
proc_version_len = strlen(op->proc_version_string);
interface_len = nv_get_file_length(op->interface);
total_len = CONSTANT_LENGTH +
- description_len + proc_version_len + interface_len;
+ version_len + description_len + proc_version_len + interface_len;
/* compute the crc of the kernel interface */
@@ -528,17 +513,14 @@ int pack(Options *op)
/* write the version */
- encode_uint32(op->major, data);
- memcpy(&(out[offset]), data, 4);
- offset += 4;
-
- encode_uint32(op->minor, data);
- memcpy(&(out[offset]), data, 4);
- offset += 4;
-
- encode_uint32(op->patch, data);
+ encode_uint32(version_len, data);
memcpy(&(out[offset]), data, 4);
offset += 4;
+
+ if (version_len) {
+ memcpy(&(out[offset]), op->version, version_len);
+ offset += version_len;
+ }
/* write the description */
@@ -593,8 +575,8 @@ int unpack(Options *op)
{
int dst_fd, fd, ret, offset, len = 0;
char *buf, *dst;
- uint32 crc, major, minor, patch, val, size;
- char *description, *proc_version_string;
+ uint32 crc, val, size;
+ char *version, *description, *proc_version_string;
fd = dst_fd = 0;
buf = dst = NULL;
@@ -635,10 +617,17 @@ int unpack(Options *op)
/* read the version */
- major = decode_uint32(buf + offset + 0);
- minor = decode_uint32(buf + offset + 4);
- patch = decode_uint32(buf + offset + 8);
- offset += 12;
+ val = decode_uint32(buf + offset);
+ offset += 4;
+
+ if (val > 0) {
+ version = nv_alloc(val+1);
+ memcpy(version, buf + offset, val);
+ version[val] = '\0';
+ } else {
+ version = NULL;
+ }
+ offset += val;
/* read the description */
@@ -677,7 +666,7 @@ int unpack(Options *op)
if (op->info) {
printf("description: %s\n", description);
- printf("version: %d.%d-%d\n", major, minor, patch);
+ printf("version: %s\n", version);
printf("crc: %u\n", crc);
printf("proc version: %s\n", proc_version_string);
return 0;
diff --git a/nvLegacy.h b/nvLegacy.h
index 56e13d6..9fb21fe 100644
--- a/nvLegacy.h
+++ b/nvLegacy.h
@@ -60,7 +60,7 @@ static const LEGACY_INFO LegacyList[] = {
{ 0x0177, 2, "GeForce4 460 Go" },
{ 0x0178, 2, "Quadro4 550 XGL" },
{ 0x0179, 2, "GeForce4 440 Go 64M" },
- { 0x017A, 2, "Quadro NVS" },
+ { 0x017A, 2, "Quadro NVS 400" },
{ 0x017C, 2, "Quadro4 500 GoGL" },
{ 0x017D, 2, "GeForce4 410 Go 16M" },
{ 0x0181, 2, "GeForce4 MX 440 with AGP8X" },
diff --git a/nvidia-installer.h b/nvidia-installer.h
index c5df1e8..9d40a70 100644
--- a/nvidia-installer.h
+++ b/nvidia-installer.h
@@ -229,10 +229,8 @@ typedef struct __package_entry {
typedef struct __package {
- int major, minor, patch;
-
char *description;
- char *version_string;
+ char *version;
char *kernel_module_filename;
char *kernel_interface_filename;
char *kernel_module_name;
diff --git a/precompiled.c b/precompiled.c
index ae91390..877f04a 100644
--- a/precompiled.c
+++ b/precompiled.c
@@ -47,7 +47,7 @@
#include "misc.h"
#include "crc.h"
-#define PRECOMPILED_CONSTANT_LENGTH (8 + 4 + 12 + 4 + 4)
+#define PRECOMPILED_CONSTANT_LENGTH (8 + 4 + 4 + 4 + 4)
/*
* decode_uint32() - given an index into a buffer, read the next 4
@@ -153,14 +153,12 @@ PrecompiledInfo *precompiled_unpack(Options *op,
const char *filename,
const char *output_filename,
const char *real_proc_version_string,
- const int package_major,
- const int package_minor,
- const int package_patch)
+ const char *package_version)
{
int dst_fd, fd, offset, len = 0;
char *buf, *dst;
- uint32 crc, major, minor, patch, val, size;
- char *description, *proc_version_string;
+ uint32 crc, val, size;
+ char *version, *description, *proc_version_string;
struct stat stat_buf;
PrecompiledInfo *info = NULL;
@@ -216,17 +214,26 @@ PrecompiledInfo *precompiled_unpack(Options *op,
/* read the version */
- major = decode_uint32(buf + offset + 0);
- minor = decode_uint32(buf + offset + 4);
- patch = decode_uint32(buf + offset + 8);
- offset += 12;
+ val = decode_uint32(buf + offset);
+ offset += 4;
+ if ((val + PRECOMPILED_CONSTANT_LENGTH) > size) {
+ ui_expert(op, "Invalid file '%s' (bad version string length %d).",
+ filename, val);
+ goto done;
+ }
+ if (val > 0) {
+ version = nvalloc(val+1);
+ memcpy(version, buf + offset, val);
+ version[val] = '\0';
+ } else {
+ version = NULL;
+ }
+ offset += val;
/* check if this precompiled kernel interface is the right driver
version */
- if ((major != package_major) ||
- (minor != package_minor) ||
- (patch != package_patch)) {
+ if (strcmp(version, package_version) != 0) {
goto done;
}
@@ -312,9 +319,7 @@ PrecompiledInfo *precompiled_unpack(Options *op,
info = (PrecompiledInfo *) nvalloc(sizeof(PrecompiledInfo));
info->crc = crc;
- info->major = major;
- info->minor = minor;
- info->patch = patch;
+ info->version = version;
info->proc_version_string = proc_version_string;
info->description = description;
diff --git a/precompiled.h b/precompiled.h
index 38bac24..8f784c0 100644
--- a/precompiled.h
+++ b/precompiled.h
@@ -33,9 +33,7 @@
typedef struct {
uint32 crc;
- uint32 major;
- uint32 minor;
- uint32 patch;
+ char *version;
char *proc_version_string;
char *description;
@@ -48,9 +46,7 @@ PrecompiledInfo *precompiled_unpack(Options *op,
const char *filename,
const char *output_filename,
const char *real_proc_version_string,
- const int package_major,
- const int package_minor,
- const int package_patch);
+ const char *package_version);
#endif /* __NVIDIA_INSTALLER_PRECOMPILED_H__ */
diff --git a/sanity.c b/sanity.c
index 3af6796..dba0ee3 100644
--- a/sanity.c
+++ b/sanity.c
@@ -45,14 +45,14 @@
int sanity(Options *op)
{
- char *descr;
- int major, minor, patch;
+ char *descr, *version;
+ int ret;
/* check that there's a driver installed at all */
- descr = get_installed_driver_version_and_descr(op, &major, &minor, &patch);
+ ret = get_installed_driver_version_and_descr(op, &version, &descr);
- if (!descr) {
+ if (!ret) {
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.");
@@ -60,9 +60,9 @@ int sanity(Options *op)
}
ui_message(op, "The currently installed driver is: '%s' "
- "(version: %d.%d-%d). nvidia-installer will now check "
+ "(version: %s). nvidia-installer will now check "
"that all installed files still exist.",
- descr, major, minor, patch);
+ descr, version);
/* check that all the files are still where we placed them */
@@ -91,11 +91,12 @@ int sanity(Options *op)
* etc).
*/
- ui_message(op, "'%s' (version: %d.%d-%d) appears to be installed "
- "correctly.", descr, major, minor, patch);
+ ui_message(op, "'%s' (version: %s) appears to be installed "
+ "correctly.", descr, version);
nvfree(descr);
-
+ nvfree(version);
+
return TRUE;
} /* sanity() */
diff --git a/update.c b/update.c
index 3a7985d..3615db5 100644
--- a/update.c
+++ b/update.c
@@ -41,8 +41,8 @@
#include "update.h"
-static char *get_latest_driver_version_and_filename(Options *op,
- int *, int *, int *);
+static int get_latest_driver_version_and_filename(Options *op,
+ char **, char **);
@@ -53,26 +53,38 @@ static char *get_latest_driver_version_and_filename(Options *op,
int update(Options *op)
{
- char *descr, *filename, *tmpfile, *url, *cmd;
- int x0, y0, z0, x1, y1, z1, ret, fd;
-
- descr = get_installed_driver_version_and_descr(op, &x0, &y0, &z0);
+ char *descr = NULL;
+ char *filename = NULL;
+ char *tmpfile = NULL;
+ char *url = NULL;
+ char *cmd;
+ char *installedVersion = NULL;
+ char *latestVersion = NULL;
+ int fd, installedRet, latestRet, localRet;
+ int ret = FALSE;
+
+ installedRet = get_installed_driver_version_and_descr(op,
+ &installedVersion,
+ &descr);
- filename = get_latest_driver_version_and_filename(op, &x1, &y1, &z1);
- if (!filename) return FALSE;
-
- if (descr && !op->force_update) {
+ latestRet = get_latest_driver_version_and_filename(op, &latestVersion,
+ &filename);
+ if (!latestRet) {
+ goto done;
+ }
+
+ if (installedRet && !op->force_update) {
/*
* if the currently installed driver version is the same as
* the latest, don't update.
*/
-
- if ((x0 == x1) && (y0 == y1) && (z0 == z1)) {
- ui_message(op, "The latest %s (version %d.%d-%d) is already "
- "installed.", descr, x0, y0, z0);
- nvfree(descr);
- return TRUE;
+
+ if (strcmp(installedVersion, latestVersion) == 0) {
+ ui_message(op, "The latest %s (version %s) is already "
+ "installed.", descr, installedVersion);
+ ret = TRUE;
+ goto done;
}
}
@@ -81,20 +93,19 @@ int update(Options *op)
tmpfile = nvstrcat(op->tmpdir, "/nv-update-XXXXXX", NULL);
url = nvstrcat(op->ftp_site, "/XFree86/", INSTALLER_OS, "-",
INSTALLER_ARCH, "/", filename, NULL);
- nvfree(filename);
-
+
/* create the temporary file */
if ((fd = mkstemp(tmpfile)) == -1) {
ui_error(op, "Unable to create temporary file (%s)", strerror(errno));
- return FALSE;
+ goto done;
}
/* download the file */
if (!snarf(op, url, fd, SNARF_FLAGS_STATUS_BAR)) {
ui_error(op, "Unable to download driver %s.", url);
- return FALSE;
+ goto done;
}
close(fd);
@@ -104,12 +115,12 @@ int update(Options *op)
/* check the binary */
cmd = nvstrcat("sh ", tmpfile, " --check", NULL);
- ret = run_command(op, cmd, NULL, FALSE, FALSE, TRUE);
+ localRet = run_command(op, cmd, NULL, FALSE, FALSE, TRUE);
nvfree(cmd);
- if (ret != 0) {
- ui_error(op, "The downloaded file does not pass its integrety check.");
- return FALSE;
+ if (localRet != 0) {
+ ui_error(op, "The downloaded file does not pass its integrity check.");
+ goto done;
}
/*
@@ -122,7 +133,7 @@ int update(Options *op)
/* execute `sh <downloaded file> <arguments>` */
cmd = nvstrcat("sh ", tmpfile, " ", op->update_arguments, NULL);
- ret = system(cmd);
+ localRet = system(cmd);
nvfree(cmd);
/* remove the downloaded file */
@@ -134,10 +145,22 @@ int update(Options *op)
* function.
*/
- exit(ret);
+ exit(localRet);
- return TRUE;
+ ret = TRUE;
+
+ done:
+ nvfree(installedVersion);
+ nvfree(descr);
+ nvfree(latestVersion);
+ nvfree(filename);
+
+ nvfree(tmpfile);
+ nvfree(url);
+
+ return ret;
+
} /* update() */
@@ -148,32 +171,42 @@ int update(Options *op)
int report_latest_driver_version(Options *op)
{
- char *descr, *filename, *url;
- int x0, y0, z0, x1, y1, z1;
+ char *descr = NULL;
+ char *filename = NULL;
+ char *url = NULL;
+ char *installedVersion = NULL;
+ char *latestVersion = NULL;
+ int installedRet, latestRet;
- descr = get_installed_driver_version_and_descr(op, &x0, &y0, &z0);
+ installedRet = get_installed_driver_version_and_descr(op,
+ &installedVersion,
+ &descr);
- filename = get_latest_driver_version_and_filename(op, &x1, &y1, &z1);
-
- if (!filename) {
+ latestRet = get_latest_driver_version_and_filename(op, &latestVersion,
+ &filename);
+
+ if (!latestRet) {
nvfree(descr);
+ nvfree(installedVersion);
return FALSE;
}
url = nvstrcat(op->ftp_site, "/XFree86/", INSTALLER_OS, "-",
INSTALLER_ARCH, "/", filename, NULL);
- if (descr) {
- ui_message(op, "Currently installed version: %d.%d-%d; "
- "latest available version: %d.%d-%d; latest driver "
- "file: %s.", x0, y0, z0, x1, y1, z1, url);
- nvfree(descr);
+ if (installedRet) {
+ ui_message(op, "Currently installed version: %s; "
+ "latest available version: %s; latest driver "
+ "file: %s.", installedVersion, latestVersion, url);
} else {
- ui_message(op, "Latest version: %d.%d-%d; latest driver file: %s.",
- x1, y1, z1, url);
+ ui_message(op, "Latest version: %s; latest driver file: %s.",
+ latestVersion, url);
}
+ nvfree(descr);
+ nvfree(installedVersion);
nvfree(filename);
+ nvfree(latestVersion);
nvfree(url);
return TRUE;
@@ -216,20 +249,35 @@ char *append_update_arguments(char *s, int c, const char *arg,
/*
- * get_latest_driver_version() -
+ * get_latest_driver_version() - download and parse the latest.txt
+ * file; the format of this file is:
+ *
+ * [old format version] [path to .run file]
+ * [new format version]
+ *
+ * This is done for backwards compatibility -- old nvidia-installers
+ * will read only the first line and parse the old format version
+ * string; new nvidia-installers will try to find the version string
+ * on the second line. If we are unable to find the version string on
+ * the second line, then fall back to the old format string on the
+ * first line.
*/
-static char *get_latest_driver_version_and_filename(Options *op, int *major,
- int *minor, int *patch)
+static int get_latest_driver_version_and_filename(Options *op,
+ char **pVersion,
+ char **pFileName)
{
int fd = -1;
int length;
+ int ret = FALSE;
char *tmpfile = NULL;
char *url = NULL;
char *str = (void *) -1;
char *s = NULL;
char *buf = NULL;
- char *filename = NULL;
+ char *buf2 = NULL;
+ char *ptr;
+ char *version = NULL;
struct stat stat_buf;
tmpfile = nvstrcat(op->tmpdir, "/nv-latest-XXXXXX", NULL);
@@ -264,10 +312,20 @@ static char *get_latest_driver_version_and_filename(Options *op, int *major,
goto done;
}
- buf = get_next_line(str, NULL, str, length);
+
+ /*
+ * read in the first two lines from the file; the second line may
+ * optionally contain a version string with the new format
+ */
+
+ buf = get_next_line(str, &ptr, str, length);
+ buf2 = get_next_line(ptr, NULL, str, length);
- if (!nvid_version(buf, major, minor, patch)) {
- ui_error(op, "Unable to determine latest NVIDIA %s-%s driver "
+ version = extract_version_string(buf2);
+ if (!version) version = extract_version_string(buf);
+
+ if (!version) {
+ ui_error(op, "Unable to determine latest NVIDIA driver "
"version (no version number found in %s)", url);
goto done;
}
@@ -281,19 +339,24 @@ static char *get_latest_driver_version_and_filename(Options *op, int *major,
}
s++;
- filename = nvstrdup(s);
+ *pFileName = nvstrdup(s);
+ *pVersion = strdup(version);
+
+ ret = TRUE;
done:
- if (buf) nvfree(buf);
+ nvfree(buf);
+ nvfree(buf2);
if (str != (void *) -1) munmap(str, stat_buf.st_size);
if (fd != -1) close(fd);
unlink(tmpfile);
- if (tmpfile) nvfree(tmpfile);
- if (url) nvfree(url);
+ nvfree(tmpfile);
+ nvfree(url);
+ nvfree(version);
- return filename;
+ return ret;
} /* get_latest_driver_version() */