Skip to content

Commit

Permalink
Moved a bunch of the versioning stuff into mojopatch.c and cleaned up…
Browse files Browse the repository at this point in the history
… patch

 skipping. This cleans up a lot of stuff and gets rid of the bogus "Patching
 successful" message box on errors.
  • Loading branch information
icculus committed May 18, 2005
1 parent 28128ed commit 3a20ac6
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 61 deletions.
126 changes: 92 additions & 34 deletions mojopatch.c
Expand Up @@ -170,14 +170,21 @@ typedef enum
ZLIB_UNCOMPRESS
} ZlibOptions;

typedef enum
{
ISPATCHABLE_ERROR,
ISPATCHABLE_YES,
ISPATCHABLE_NO,
ISPATCHABLE_MATCHES,
} IsPatchable;

static int debug = 0;
static int interactive = 0;
static int replace = 0;
static int appending = 0;
static int alwaysadd = 0;
static int quietonsuccess = 0;
static int skip_patch = 0;
static int skip_patch = 0; /* global flag to skip current patch. */
static int zliblevel = 9;
static PatchCommands command = COMMAND_NONE;

Expand Down Expand Up @@ -592,17 +599,22 @@ static void _current_operation(const char *fmt, ...)
} /* _current_operation */


/* don't taunt this function. */
int version_ok(const char *ver, const char *allowed_ver, const char *newver)
/* !!! FIXME: don't taunt this function. */
/*
* ver == installed app's current version.
* allowed_ver == allowed versions ("123", "123 or 456", "less than 789").
* newver == version that patched app will become.
*/
IsPatchable version_ok(const char *ver, const char *allowed_ver, const char *newver)
{
char *ptr;
char *buf;

if (*allowed_ver == '\0')
return 1; /* No specified version? Anything is okay, then. */
if (*allowed_ver == '\0') /* No specified version? Anything is okay. */
return ISPATCHABLE_YES;

if (strcmp(allowed_ver, newver) == 0)
return -1; /* all patched up. */
if (strcmp(allowed_ver, newver) == 0) /* all patched up? */
return ISPATCHABLE_MATCHES;

buf = (char *) alloca(strlen(allowed_ver) + 1);
strcpy(buf, allowed_ver);
Expand All @@ -618,33 +630,62 @@ int version_ok(const char *ver, const char *allowed_ver, const char *newver)

dver = strtod(ver, &endptr);
if (endptr == ver)
return 0;
return ISPATCHABLE_ERROR;

dallow = strtod(ptr, &endptr);
if (endptr == ptr)
return 0;
return ISPATCHABLE_ERROR;

if (dver < dallow)
return(1);
else if (dver == dallow)
return(-1);
return(ISPATCHABLE_YES);

return(0);
return(ISPATCHABLE_NO);
} /* if */

while ((ptr = strstr(buf, " or ")) != NULL)
{
*ptr = '\0';
if (strcmp(ver, buf) == 0)
return(1);
return(ISPATCHABLE_YES);

buf = ptr + 4;
} /* while */

return(strcmp(ver, buf) == 0);
return( (strcmp(ver, buf) == 0) ? ISPATCHABLE_YES : ISPATCHABLE_NO );
} /* version_ok */


static IsPatchable check_product_version(const char *ident,
const char *version,
const char *newversion)
{
char buf[128];
IsPatchable retval = ISPATCHABLE_ERROR;

if (!get_product_version(ident, buf, sizeof (buf)))
_fatal("Can't determine product's installed version.");
else
{
retval = version_ok(buf, version, newversion);
if (retval == ISPATCHABLE_MATCHES)
_fatal("You seem to be all patched up already!");
else if (retval == ISPATCHABLE_ERROR)
_fatal("This patch is misbuilt! Contact your vendor!");
else if (retval == ISPATCHABLE_NO)
{
_fatal("This patch applies to version '%s', but you have '%s'.",
version, buf);
} /* else */
else
{
assert(retval == ISPATCHABLE_YES);
} /* else */
} /* else */

return(retval);
} /* check_product_version */


static int _do_xdelta(const char *fmt, ...)
{
char buf[512];
Expand Down Expand Up @@ -2061,8 +2102,7 @@ static int manually_locate_product(const char *name, char *buf, size_t bufsize)
} /* manually_locate_product */


static int chdir_by_identifier(const char *name, const char *str,
const char *version, const char *newversion)
static int chdir_by_identifier(const char *name, const char *str)
{
char buf[MAXPATHLEN];
int hasident = ((str != NULL) && (*str));
Expand Down Expand Up @@ -2092,7 +2132,7 @@ static int chdir_by_identifier(const char *name, const char *str,
return(0);
} /* if */

return(check_product_version(str, version, newversion));
return(1);
} /* chdir_by_identifier */


Expand Down Expand Up @@ -2127,16 +2167,23 @@ static int process_patch_header(SerialArchive *ar, PatchHeader *h)

if (!info_only())
{
int rc = chdir_by_identifier(h->product, h->identifier,
h->version, h->newversion);
if (rc != 1)
skip_patch = 1;
} /* if */

if (*h->readmefname)
{
if (!info_only())
retval = show_and_install_readme(h->readmefname, h->readmedata);
if (!chdir_by_identifier(h->product, h->identifier))
retval = PATCHERROR;
else
{
IsPatchable rc;
rc = check_product_version(h->identifier, h->version, h->newversion);
if (rc == ISPATCHABLE_ERROR)
retval = PATCHERROR;
else if ((rc == ISPATCHABLE_MATCHES) || (rc == ISPATCHABLE_NO))
skip_patch = 1;
else
{
assert(rc == ISPATCHABLE_YES);
if (*h->readmefname)
retval = show_and_install_readme(h->readmefname, h->readmedata);
} /* else */
} /* else */
} /* if */

free(h->readmedata);
Expand All @@ -2151,6 +2198,8 @@ static int do_patching(void)
SerialArchive ar;
int report_error = 0;
int retval = PATCHERROR;
int installed_patches = 0;
int skipped_patches = 0;
long file_size = 0; /* !!! FIXME: make this size_t? */
int do_progress = 0;

Expand Down Expand Up @@ -2179,7 +2228,7 @@ static int do_patching(void)
if (do_patch_operations(&ar, do_progress, file_size) == PATCHERROR)
goto do_patching_done;

if (!info_only())
if ((!info_only()) && (!skip_patch))
{
_current_operation("Updating product version...");
ui_total_progress(-1);
Expand All @@ -2198,20 +2247,29 @@ static int do_patching(void)
} /* if */
} /* if */

skip_patch = 0; /* reset for next patch... */
if (!skip_patch)
installed_patches++;
else
{
skipped_patches++;
skip_patch = 0; /* reset for next patch... */
} /* else */

/* !!! FIXME: This loses command line overrides! */
memset(&header, '\0', sizeof (header));

report_error = 0;
} /* while */

close_serialized_archive(&ar);

retval = PATCHSUCCESS;
ui_total_progress(100);
if ( (!info_only()) && (!quietonsuccess) )
ui_success("Patching successful!");
if (!info_only())
{
if (installed_patches == 0)
_fatal("Your installation has not been modified.");
else if (!quietonsuccess)
ui_success("Patching successful!");
}

do_patching_done:
close_serialized_archive(&ar);
Expand Down
5 changes: 1 addition & 4 deletions platform.h
Expand Up @@ -49,9 +49,6 @@ void _log(const char *fmt, ...);
/* Call this for logging (debug info). */
void _dlog(const char *fmt, ...);

/* Does a given version match the requirements? */
int version_ok(const char *ver, const char *allowed, const char *newver);

/* platform-specific stuff you implement. */
int file_exists(const char *fname);
int file_is_directory(const char *fname);
Expand All @@ -64,7 +61,7 @@ int spawn_xdelta(const char *cmdline);
int update_version(const char *ver);
int calc_tmp_filenames(char **tmp1, char **tmp2);
int locate_product_by_identifier(const char *str, char *buf, size_t bufsize);
int check_product_version(const char *ident, const char *version, const char *newversion);
int get_product_version(const char *ident, char *buf, size_t bufsize);

#ifdef __cplusplus
}
Expand Down
42 changes: 19 additions & 23 deletions platform_unix.c
Expand Up @@ -290,8 +290,8 @@ static char *find_info_plist_bundle_id(char *ptr)
#endif /* PLATFORM_MACOSX */


int check_product_version(const char *ident, const char *version,
const char *newversion)
/* you are already chdir()'d when this is called. */
int get_product_version(const char *ident, char *buf, size_t bufsize)
{
#if PLATFORM_MACOSX
const char *fname = "Contents/Info.plist"; /* already chdir'd for this. */
Expand All @@ -300,7 +300,6 @@ int check_product_version(const char *ident, const char *version,
long fsize;
int retval = 0;
FILE *io = NULL;
int knowver = 0;

if ( !get_file_size(fname, &fsize) ) goto parse_info_plist_bailed;
if ( (mem = malloc(fsize + 1)) == NULL ) goto parse_info_plist_bailed;
Expand Down Expand Up @@ -333,31 +332,25 @@ int check_product_version(const char *ident, const char *version,
fclose(io);

ptr = find_info_plist_version(mem);
if (ptr != NULL)
{
knowver = 1;
retval = version_ok(ptr, version, newversion);
if (retval == -1)
_fatal("You seem to be all patched up already!");
else if (retval == 0)
{
_fatal("This patch applies to version '%s', but you have '%s'.",
version, ptr);
} /* else */
} /* if */
if (ptr == NULL)
return(0);

strncpy(buf, ptr, bufsize);
buf[bufsize-1] = '\0';
retval = 1;

parse_info_plist_bailed:
free(mem);
if (io != NULL)
fclose(io);

if (!knowver) _fatal("Can't determine product's installed version.");
return(retval);
#else
_fatal("Not implemented!"); /* !!! FIXME */
*buf = '\0';
return(0);
#endif
} /* parse_info_dot_plist */
} /* check_product_version */


int locate_product_by_identifier(const char *str, char *buf, size_t bufsize)
Expand All @@ -369,18 +362,21 @@ int locate_product_by_identifier(const char *str, char *buf, size_t bufsize)
CFStringRef id = CFStringCreateWithBytes(NULL, str, strlen(str),
kCFStringEncodingISOLatin1, 0);

/*
* !!! FIXME: This has a tendency to find installs in the trashcan. :/
* !!! FIXME: It might be worth checking if the product install has
* !!! FIXME: a dir named ".Trash" in the hierarchy, and considering
* !!! FIXME: it not found if so.
*/
rc = LSFindApplicationForInfo(kLSUnknownCreator, id, NULL, NULL, &url);
CFRelease(id);
if (rc == noErr)
{
Boolean b = CFURLGetFileSystemRepresentation(url, TRUE, buf, bufsize);
CFRelease(url);
if (1) //((b) && (strstr(buf, "/.Trash/")))
{
_fatal("It looks like your installation is in the Trash can."
" Please take it out of the trash first."
" If this is an old installation, please empty your"
" trash so we find the right one.");
b = 0;
} /* if */

return(b != 0);
} /* if */

Expand Down

0 comments on commit 3a20ac6

Please sign in to comment.