diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:20:38 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:20:38 -0800 |
commit | 4d3c391aebad3c67ef9e77eba3fe86acc79541f5 (patch) | |
tree | 36bca53f74716b5bd9c474c0ef933006faf1a2bb | |
parent | 184ddefeab802bc3b119c49dede0d49fc5e01670 (diff) |
100.14.03100.14.03
-rw-r--r-- | DRIVER_VERSION | 2 | ||||
-rw-r--r-- | backup.c | 239 | ||||
-rw-r--r-- | backup.h | 3 | ||||
-rw-r--r-- | command-list.c | 35 | ||||
-rw-r--r-- | files.c | 214 | ||||
-rw-r--r-- | install-from-cwd.c | 133 | ||||
-rw-r--r-- | kernel.c | 58 | ||||
-rw-r--r-- | kernel.h | 1 | ||||
-rw-r--r-- | misc.c | 222 | ||||
-rw-r--r-- | misc.h | 2 | ||||
-rw-r--r-- | mkprecompiled.c | 87 | ||||
-rw-r--r-- | nvLegacy.h | 2 | ||||
-rw-r--r-- | nvidia-installer.h | 4 | ||||
-rw-r--r-- | precompiled.c | 37 | ||||
-rw-r--r-- | precompiled.h | 8 | ||||
-rw-r--r-- | sanity.c | 19 | ||||
-rw-r--r-- | update.c | 167 |
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 @@ -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() */ @@ -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; @@ -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() */ @@ -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() */ @@ -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*); @@ -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; } @@ -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; @@ -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__ */ @@ -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() */ @@ -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() */ |