summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2008-02-13 10:21:37 -0800
committerAaron Plattner <aplattner@nvidia.com>2008-02-13 10:21:37 -0800
commit2b28038f0c31d049ba9e6d7e3dfdc8c437bf87a1 (patch)
treeede6ea53266f0443fe4bf5923db6ec5498737cc5
parent2237736ab7b463710696a5c979931852528bf78e (diff)
96.43.0196.43.01
-rw-r--r--DRIVER_VERSION2
-rw-r--r--backup.c175
-rw-r--r--backup.h3
-rw-r--r--command-list.c35
-rw-r--r--command-list.h2
-rw-r--r--files.c132
-rw-r--r--install-from-cwd.c82
-rw-r--r--kernel.c52
-rw-r--r--kernel.h1
-rw-r--r--misc.c222
-rw-r--r--misc.h2
-rw-r--r--mkprecompiled.c87
-rw-r--r--nvidia-installer.h20
-rw-r--r--precompiled.c37
-rw-r--r--precompiled.h8
-rw-r--r--sanity.c19
-rw-r--r--update.c167
17 files changed, 672 insertions, 374 deletions
diff --git a/DRIVER_VERSION b/DRIVER_VERSION
index ea7fd6a..20723f9 100644
--- a/DRIVER_VERSION
+++ b/DRIVER_VERSION
@@ -1 +1 @@
-1.0-9639
+96.43.01
diff --git a/backup.c b/backup.c
index 85e2130..95d6839 100644
--- a/backup.c
+++ b/backup.c
@@ -126,7 +126,7 @@ 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 +141,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 +169,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) {
@@ -982,12 +987,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 +1007,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;
- if (!nvid_version(version, major, minor, patch)) goto done;
+ version = extract_version_string(version_line);
+
+ 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,30 +1053,30 @@ 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;
- 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;
} 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);
+ "%s, but the kernel module is %s.\n",
+ version, p->version);
return FALSE;
} else {
return TRUE;
@@ -1064,7 +1084,12 @@ int check_for_existing_driver(Options *op, Package *p)
}
}
- 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 +1100,25 @@ 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;
}
- free(descr);
- return TRUE;
+ ret = TRUE;
+
+ done:
+
+ nvfree(descr);
+ nvfree(version);
+
+ return ret;
} /* check_for_existing_driver() */
@@ -1103,11 +1134,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 +1150,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 +1176,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() */
@@ -1330,3 +1365,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 e604a20..aa3f283 100644
--- a/command-list.c
+++ b/command-list.c
@@ -65,6 +65,8 @@ static void find_conflicting_kernel_modules(Options *op,
static void find_existing_files(Package *p, FileList *l, unsigned int);
+static void condense_file_list(Package *p, FileList *l);
+
static void add_command (CommandList *c, int cmd, ...);
static void add_file_to_list(const char*, const char*, FileList*);
@@ -180,7 +182,7 @@ CommandList *build_command_list(Options *op, Package *p)
/* condense the file list */
- condense_file_list(l);
+ condense_file_list(p, l);
/* check the conflicting file list for any installed files */
@@ -716,10 +718,10 @@ static void find_conflicting_libraries(Options *op,
* brute-force algorithm.
*/
-void condense_file_list(FileList *l)
+static void condense_file_list(Package *p, FileList *l)
{
char **s = NULL;
- int n = 0, i, j, match;
+ int n = 0, i, j, keep;
struct stat stat_buf, *stat_bufs;
@@ -741,12 +743,27 @@ void condense_file_list(FileList *l)
*/
for (i = 0; i < l->num; i++) {
- match = FALSE;
+ keep = TRUE;
if (lstat(l->filename[i], &stat_buf) == -1)
continue;
-
- for (j = 0; j < n; j++) {
+
+ /*
+ * check if this file is in the package we're trying to
+ * install; we don't want to remove files that are in the
+ * package; symlinks may have tricked us into looking for
+ * conflicting files inside our unpacked .run file.
+ */
+
+ for (j = 0; j < p->num_entries; j++) {
+ if ((p->entries[j].device == stat_buf.st_dev) &&
+ (p->entries[j].inode == stat_buf.st_ino)) {
+ keep = FALSE;
+ break;
+ }
+ }
+
+ for (j = 0; keep && (j < n); j++) {
/*
* determine if the two files are the same by comparing
@@ -755,12 +772,12 @@ void condense_file_list(FileList *l)
if ((stat_buf.st_dev == stat_bufs[j].st_dev) &&
(stat_buf.st_ino == stat_bufs[j].st_ino)) {
- match = TRUE;
+ keep = FALSE;
break;
}
}
-
- if (!match) {
+
+ if (keep) {
s = (char **) nvrealloc(s, sizeof(char *) * (n + 1));
s[n] = nvstrdup(l->filename[i]);
stat_bufs[n] = stat_buf;
diff --git a/command-list.h b/command-list.h
index 6b2d225..5e70a1e 100644
--- a/command-list.h
+++ b/command-list.h
@@ -83,6 +83,4 @@ CommandList *build_command_list(Options*, Package *);
void free_command_list(Options*, CommandList*);
int execute_command_list(Options*, CommandList*, const char*, const char*);
-void condense_file_list(FileList *l);
-
#endif /* __NVIDIA_INSTALLER_COMMAND_LIST_H__ */
diff --git a/files.c b/files.c
index 77b5449..d698980 100644
--- a/files.c
+++ b/files.c
@@ -872,35 +872,26 @@ int get_prefixes (Options *op)
int add_kernel_module_to_package(Options *op, Package *p)
{
- int n, len;
+ char *file, *name, *dst;
- n = p->num_entries;
-
- p->entries =
- (PackageEntry *) nvrealloc(p->entries, (n + 1) * sizeof(PackageEntry));
+ file = nvstrcat(p->kernel_module_build_directory, "/",
+ p->kernel_module_filename, NULL);
- len = strlen(p->kernel_module_build_directory) +
- strlen(p->kernel_module_filename) + 2;
- p->entries[n].file = (char *) nvalloc(len);
- snprintf(p->entries[n].file, len, "%s/%s",
- p->kernel_module_build_directory, p->kernel_module_filename);
-
- p->entries[n].path = NULL;
- p->entries[n].target = NULL;
- p->entries[n].flags = FILE_TYPE_KERNEL_MODULE;
- p->entries[n].mode = 0644;
-
- p->entries[n].name = strrchr(p->entries[n].file, '/');
- if (p->entries[n].name) p->entries[n].name++;
- if (!p->entries[n].name) p->entries[n].name = p->entries[n].file;
-
- len = strlen(op->kernel_module_installation_path) +
- strlen(p->kernel_module_filename) + 2;
- p->entries[n].dst = (char *) nvalloc(len);
- snprintf (p->entries[n].dst, len, "%s/%s",
- op->kernel_module_installation_path, p->kernel_module_filename);
-
- p->num_entries++;
+ name = strrchr(file, '/');
+ if (name) name++;
+ if (!name) name = file;
+
+ dst = nvstrcat(op->kernel_module_installation_path, "/",
+ p->kernel_module_filename, NULL);
+
+ add_package_entry(p,
+ file,
+ NULL, /* path */
+ name,
+ NULL, /* target */
+ dst,
+ FILE_TYPE_KERNEL_MODULE,
+ 0644);
return TRUE;
@@ -1408,7 +1399,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;
@@ -1429,12 +1419,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);
@@ -1450,12 +1434,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 */
@@ -1718,7 +1700,7 @@ done:
void process_libGL_la_files(Options *op, Package *p)
{
- int i, n;
+ int i;
char *tmpfile;
char *tokens[3] = { "__LIBGL_PATH__", "__GENERATED_BY__", NULL };
@@ -1750,22 +1732,25 @@ void process_libGL_la_files(Options *op, Package *p)
if (tmpfile != NULL) {
/* add this new file to the package */
-
- n = p->num_entries;
-
- p->entries =
- (PackageEntry *) nvrealloc(p->entries,
- (n + 1) * sizeof(PackageEntry));
- p->entries[n].file = tmpfile;
- p->entries[n].path = p->entries[i].path;
- p->entries[n].target = NULL;
- p->entries[n].flags = ((p->entries[i].flags & FILE_CLASS_MASK)
- | FILE_TYPE_LIBGL_LA);
- p->entries[n].mode = p->entries[i].mode;
-
- p->entries[n].name = nvstrdup(p->entries[i].name);
-
- p->num_entries++;
+
+ /*
+ * XXX 'name' is the basename (non-directory part) of
+ * the file to be installed; normally, 'name' just
+ * points into 'file', but in this case 'file' is
+ * mkstemp(3)-generated, so doesn't have the same
+ * basename; instead, we just strdup the name from the
+ * template package entry; yes, 'name' will get leaked
+ */
+
+ add_package_entry(p,
+ tmpfile,
+ p->entries[i].path,
+ nvstrdup(p->entries[i].name),
+ NULL, /* target */
+ NULL, /* dst */
+ ((p->entries[i].flags & FILE_CLASS_MASK) |
+ FILE_TYPE_LIBGL_LA),
+ p->entries[i].mode);
}
nvfree(replacements[0]);
@@ -1787,7 +1772,7 @@ void process_libGL_la_files(Options *op, Package *p)
void process_dot_desktop_files(Options *op, Package *p)
{
- int i, n;
+ int i;
char *tmpfile;
char *tokens[3] = { "__UTILS_PATH__", "__PIXMAP_PATH__", NULL };
@@ -1823,22 +1808,25 @@ void process_dot_desktop_files(Options *op, Package *p)
replacements);
if (tmpfile != NULL) {
/* add this new file to the package */
-
- n = p->num_entries;
-
- p->entries =
- (PackageEntry *) nvrealloc(p->entries,
- (n + 1) * sizeof(PackageEntry));
- p->entries[n].file = tmpfile;
- p->entries[n].path = p->entries[i].path;
- p->entries[n].target = NULL;
- p->entries[n].flags = ((p->entries[i].flags & FILE_CLASS_MASK)
- | FILE_TYPE_DOT_DESKTOP);
- p->entries[n].mode = p->entries[i].mode;
-
- p->entries[n].name = nvstrdup(p->entries[i].name);
-
- p->num_entries++;
+
+ /*
+ * XXX 'name' is the basename (non-directory part) of
+ * the file to be installed; normally, 'name' just
+ * points into 'file', but in this case 'file' is
+ * mkstemp(3)-generated, so doesn't have the same
+ * basename; instead, we just strdup the name from the
+ * template package entry; yes, 'name' will get leaked
+ */
+
+ add_package_entry(p,
+ tmpfile,
+ p->entries[i].path,
+ nvstrdup(p->entries[i].name),
+ NULL, /* target */
+ NULL, /* dst */
+ ((p->entries[i].flags & FILE_CLASS_MASK) |
+ FILE_TYPE_DOT_DESKTOP),
+ p->entries[i].mode);
}
}
}
diff --git a/install-from-cwd.c b/install-from-cwd.c
index 10ff483..a8a7e9d 100644
--- a/install-from-cwd.c
+++ b/install-from-cwd.c
@@ -96,9 +96,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.
@@ -238,7 +237,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 +256,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,7 +267,7 @@ 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);
}
}
@@ -431,7 +430,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)
@@ -459,7 +458,7 @@ static Package *parse_manifest (Options *op)
char *buf, *c, *flag , *tmpstr;
int done, n, line;
int fd, len = 0;
- struct stat stat_buf;
+ struct stat stat_buf, entry_stat_buf;
Package *p;
char *manifest = MAP_FAILED, *ptr;
@@ -490,10 +489,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 */
@@ -726,7 +723,21 @@ static Package *parse_manifest (Options *op)
if (p->entries[n].name) p->entries[n].name++;
if (!p->entries[n].name) p->entries[n].name = p->entries[n].file;
-
+
+ /*
+ * store the inode and device information, so that we can
+ * later recognize it, to avoid accidentally moving it as
+ * part of the 'find_conflicting_files' path
+ */
+
+ if (stat(p->entries[n].file, &entry_stat_buf) != -1) {
+ p->entries[n].inode = entry_stat_buf.st_ino;
+ p->entries[n].device = entry_stat_buf.st_dev;
+ } else {
+ p->entries[n].inode = 0;
+ p->entries[n].device = 0;
+ }
+
/* free the line */
free(buf);
@@ -759,3 +770,48 @@ static Package *parse_manifest (Options *op)
return NULL;
} /* parse_manifest() */
+
+
+
+/*
+ * add_package_entry() - add a PackageEntry to the package's entries
+ * array.
+ */
+
+void add_package_entry(Package *p,
+ char *file,
+ char *path,
+ char *name,
+ char *target,
+ char *dst,
+ unsigned int flags,
+ mode_t mode)
+{
+ int n;
+ struct stat stat_buf;
+
+ n = p->num_entries;
+
+ p->entries =
+ (PackageEntry *) nvrealloc(p->entries, (n + 1) * sizeof(PackageEntry));
+
+ p->entries[n].file = file;
+ p->entries[n].path = path;
+ p->entries[n].name = name;
+ p->entries[n].target = target;
+ p->entries[n].dst = dst;
+ p->entries[n].flags = flags;
+ p->entries[n].mode = mode;
+
+ if (stat(p->entries[n].file, &stat_buf) != -1) {
+ p->entries[n].inode = stat_buf.st_ino;
+ p->entries[n].device = stat_buf.st_dev;
+ } else {
+ p->entries[n].inode = 0;
+ p->entries[n].device = 0;
+ }
+
+ p->num_entries++;
+
+} /* add_package_entry() */
+
diff --git a/kernel.c b/kernel.c
index e3692c4..a9c631f 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;
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 85dfab4..1ffc0b1 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.
*/
@@ -2082,7 +2206,7 @@ int check_for_nvidia_graphics_devices(Options *op, Package *p)
"through the NVIDIA legacy Linux graphics drivers. Please "
"visit http://www.nvidia.com/object/unix.html for more "
"information. The %s NVIDIA Linux graphics driver will "
- "ignore this GPU.", LegacyList[i].AdapterString, p->version_string);
+ "ignore this GPU.", LegacyList[i].AdapterString, p->version);
found_legacy_device = TRUE;
}
}
@@ -2098,7 +2222,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/nvidia-installer.h b/nvidia-installer.h
index aacc02e..5a06536 100644
--- a/nvidia-installer.h
+++ b/nvidia-installer.h
@@ -224,15 +224,21 @@ typedef struct __package_entry {
unsigned int flags;
mode_t mode;
+ ino_t inode;
+ dev_t device; /*
+ * inode of the file after extraction from the
+ * package; this is needed to compare against the
+ * files on the user's system that we consider for
+ * removal, so that symlink loops don't confuse us
+ * into deleting the files from the package.
+ */
} PackageEntry;
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;
@@ -466,6 +472,14 @@ void log_printf(Options *op, const int wb,
int install_from_cwd(Options *op);
int add_this_kernel(Options *op);
+void add_package_entry(Package *p,
+ char *file,
+ char *path,
+ char *name,
+ char *target,
+ char *dst,
+ unsigned int flags,
+ mode_t mode);
/* XXX */
typedef TextRows *(*FormatTextRows)(const char*, const char*, int, int);
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() */